diff options
Diffstat (limited to 'lib/Sema/SemaExpr.cpp')
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 450 |
1 files changed, 292 insertions, 158 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 0077d6c539c3..bb174521c72c 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -333,10 +333,8 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, Diag(Loc, diag::err_binding_cannot_appear_in_own_initializer) << D->getDeclName(); } else { - const AutoType *AT = cast<VarDecl>(D)->getType()->getContainedAutoType(); - Diag(Loc, diag::err_auto_variable_cannot_appear_in_own_initializer) - << D->getDeclName() << (unsigned)AT->getKeyword(); + << D->getDeclName() << cast<VarDecl>(D)->getType(); } return true; } @@ -706,8 +704,7 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) { // Loading a __weak object implicitly retains the value, so we need a cleanup to // balance that. - if (getLangOpts().ObjCAutoRefCount && - E->getType().getObjCLifetime() == Qualifiers::OCL_Weak) + if (E->getType().getObjCLifetime() == Qualifiers::OCL_Weak) Cleanup.setExprNeedsCleanups(true); ExprResult Res = ImplicitCastExpr::Create(Context, T, CK_LValueToRValue, E, @@ -1434,7 +1431,8 @@ Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc, // Decay and strip qualifiers for the controlling expression type, and handle // placeholder type replacement. See committee discussion from WG14 DR423. { - EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated); + EnterExpressionEvaluationContext Unevaluated( + *this, Sema::ExpressionEvaluationContext::Unevaluated); ExprResult R = DefaultFunctionArrayLvalueConversion(ControllingExpr); if (R.isInvalid()) return ExprError(); @@ -1443,7 +1441,7 @@ Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc, // The controlling expression is an unevaluated operand, so side effects are // likely unintended. - if (ActiveTemplateInstantiations.empty() && + if (!inTemplateInstantiation() && ControllingExpr->HasSideEffects(Context, false)) Diag(ControllingExpr->getExprLoc(), diag::warn_side_effects_unevaluated_context); @@ -1774,7 +1772,10 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, E->getLocStart())) recordUseOfEvaluatedWeak(E); - if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) { + FieldDecl *FD = dyn_cast<FieldDecl>(D); + if (IndirectFieldDecl *IFD = dyn_cast<IndirectFieldDecl>(D)) + FD = IFD->getAnonField(); + if (FD) { UnusedPrivateFields.remove(FD); // Just in case we're building an illegal pointer-to-member. if (FD->isBitField()) @@ -1890,9 +1891,10 @@ Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, // During a default argument instantiation the CurContext points // to a CXXMethodDecl; but we can't apply a this-> fixit inside a // function parameter list, hence add an explicit check. - bool isDefaultArgument = !ActiveTemplateInstantiations.empty() && - ActiveTemplateInstantiations.back().Kind == - ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation; + bool isDefaultArgument = + !CodeSynthesisContexts.empty() && + CodeSynthesisContexts.back().Kind == + CodeSynthesisContext::DefaultFunctionArgumentInstantiation; CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext); bool isInstance = CurMethod && CurMethod->isInstance() && @@ -2510,11 +2512,11 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, ObjCIvarRefExpr(IV, IV->getUsageType(SelfExpr.get()->getType()), Loc, IV->getLocation(), SelfExpr.get(), true, true); + if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) { + if (!Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, Loc)) + recordUseOfEvaluatedWeak(Result); + } if (getLangOpts().ObjCAutoRefCount) { - if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) { - if (!Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, Loc)) - recordUseOfEvaluatedWeak(Result); - } if (CurContext->isClosure()) Diag(Loc, diag::warn_implicitly_retains_self) << FixItHint::CreateInsertion(Loc, "self->"); @@ -3038,6 +3040,9 @@ ExprResult Sema::BuildDeclarationNameExpr( break; } + case Decl::CXXDeductionGuide: + llvm_unreachable("building reference to deduction guide"); + case Decl::MSProperty: valueKind = VK_LValue; break; @@ -3694,7 +3699,7 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *E, // The operand for sizeof and alignof is in an unevaluated expression context, // so side effects could result in unintended consequences. if ((ExprKind == UETT_SizeOf || ExprKind == UETT_AlignOf) && - ActiveTemplateInstantiations.empty() && E->HasSideEffects(Context, false)) + !inTemplateInstantiation() && E->HasSideEffects(Context, false)) Diag(E->getExprLoc(), diag::warn_side_effects_unevaluated_context); if (CheckObjCTraitOperandConstraints(*this, ExprTy, E->getExprLoc(), @@ -3969,7 +3974,8 @@ static void captureVariablyModifiedType(ASTContext &Context, QualType T, T = cast<DecltypeType>(Ty)->desugar(); break; case Type::Auto: - T = cast<AutoType>(Ty)->getDeducedType(); + case Type::DeducedTemplateSpecialization: + T = cast<DeducedType>(Ty)->getDeducedType(); break; case Type::TypeOfExpr: T = cast<TypeOfExprType>(Ty)->getUnderlyingExpr()->getType(); @@ -4553,8 +4559,8 @@ bool Sema::CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD, if (Param->hasUninstantiatedDefaultArg()) { Expr *UninstExpr = Param->getUninstantiatedDefaultArg(); - EnterExpressionEvaluationContext EvalContext(*this, PotentiallyEvaluated, - Param); + EnterExpressionEvaluationContext EvalContext( + *this, ExpressionEvaluationContext::PotentiallyEvaluated, Param); // Instantiate the expression. MultiLevelTemplateArgumentList MutiLevelArgList @@ -5378,6 +5384,15 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, return ExprError(); } + // Interrupt handlers don't save off the VFP regs automatically on ARM, + // so there's some risk when calling out to non-interrupt handler functions + // that the callee might not preserve them. This is easy to diagnose here, + // but can be very challenging to debug. + if (auto *Caller = getCurFunctionDecl()) + if (Caller->hasAttr<ARMInterruptAttr>()) + if (!FDecl || !FDecl->hasAttr<ARMInterruptAttr>()) + Diag(Fn->getExprLoc(), diag::warn_arm_interrupt_calling_convention); + // Promote the function operand. // We special-case function promotion here because we only allow promoting // builtin functions to function pointers in the callee of a call. @@ -6323,92 +6338,98 @@ static QualType checkConditionalPointerCompatibility(Sema &S, ExprResult &LHS, Qualifiers lhQual = lhptee.getQualifiers(); Qualifiers rhQual = rhptee.getQualifiers(); + unsigned ResultAddrSpace = 0; + unsigned LAddrSpace = lhQual.getAddressSpace(); + unsigned RAddrSpace = rhQual.getAddressSpace(); + if (S.getLangOpts().OpenCL) { + // OpenCL v1.1 s6.5 - Conversion between pointers to distinct address + // spaces is disallowed. + if (lhQual.isAddressSpaceSupersetOf(rhQual)) + ResultAddrSpace = LAddrSpace; + else if (rhQual.isAddressSpaceSupersetOf(lhQual)) + ResultAddrSpace = RAddrSpace; + else { + S.Diag(Loc, + diag::err_typecheck_op_on_nonoverlapping_address_space_pointers) + << LHSTy << RHSTy << 2 << LHS.get()->getSourceRange() + << RHS.get()->getSourceRange(); + return QualType(); + } + } + unsigned MergedCVRQual = lhQual.getCVRQualifiers() | rhQual.getCVRQualifiers(); + auto LHSCastKind = CK_BitCast, RHSCastKind = CK_BitCast; lhQual.removeCVRQualifiers(); rhQual.removeCVRQualifiers(); + // OpenCL v2.0 specification doesn't extend compatibility of type qualifiers + // (C99 6.7.3) for address spaces. We assume that the check should behave in + // the same manner as it's defined for CVR qualifiers, so for OpenCL two + // qual types are compatible iff + // * corresponded types are compatible + // * CVR qualifiers are equal + // * address spaces are equal + // Thus for conditional operator we merge CVR and address space unqualified + // pointees and if there is a composite type we return a pointer to it with + // merged qualifiers. + if (S.getLangOpts().OpenCL) { + LHSCastKind = LAddrSpace == ResultAddrSpace + ? CK_BitCast + : CK_AddressSpaceConversion; + RHSCastKind = RAddrSpace == ResultAddrSpace + ? CK_BitCast + : CK_AddressSpaceConversion; + lhQual.removeAddressSpace(); + rhQual.removeAddressSpace(); + } + lhptee = S.Context.getQualifiedType(lhptee.getUnqualifiedType(), lhQual); rhptee = S.Context.getQualifiedType(rhptee.getUnqualifiedType(), rhQual); - // For OpenCL: - // 1. If LHS and RHS types match exactly and: - // (a) AS match => use standard C rules, no bitcast or addrspacecast - // (b) AS overlap => generate addrspacecast - // (c) AS don't overlap => give an error - // 2. if LHS and RHS types don't match: - // (a) AS match => use standard C rules, generate bitcast - // (b) AS overlap => generate addrspacecast instead of bitcast - // (c) AS don't overlap => give an error - - // For OpenCL, non-null composite type is returned only for cases 1a and 1b. QualType CompositeTy = S.Context.mergeTypes(lhptee, rhptee); - // OpenCL cases 1c, 2a, 2b, and 2c. if (CompositeTy.isNull()) { // In this situation, we assume void* type. No especially good // reason, but this is what gcc does, and we do have to pick // to get a consistent AST. QualType incompatTy; - if (S.getLangOpts().OpenCL) { - // OpenCL v1.1 s6.5 - Conversion between pointers to distinct address - // spaces is disallowed. - unsigned ResultAddrSpace; - if (lhQual.isAddressSpaceSupersetOf(rhQual)) { - // Cases 2a and 2b. - ResultAddrSpace = lhQual.getAddressSpace(); - } else if (rhQual.isAddressSpaceSupersetOf(lhQual)) { - // Cases 2a and 2b. - ResultAddrSpace = rhQual.getAddressSpace(); - } else { - // Cases 1c and 2c. - S.Diag(Loc, - diag::err_typecheck_op_on_nonoverlapping_address_space_pointers) - << LHSTy << RHSTy << 2 << LHS.get()->getSourceRange() - << RHS.get()->getSourceRange(); - return QualType(); - } - - // Continue handling cases 2a and 2b. - incompatTy = S.Context.getPointerType( - S.Context.getAddrSpaceQualType(S.Context.VoidTy, ResultAddrSpace)); - LHS = S.ImpCastExprToType(LHS.get(), incompatTy, - (lhQual.getAddressSpace() != ResultAddrSpace) - ? CK_AddressSpaceConversion /* 2b */ - : CK_BitCast /* 2a */); - RHS = S.ImpCastExprToType(RHS.get(), incompatTy, - (rhQual.getAddressSpace() != ResultAddrSpace) - ? CK_AddressSpaceConversion /* 2b */ - : CK_BitCast /* 2a */); - } else { - S.Diag(Loc, diag::ext_typecheck_cond_incompatible_pointers) - << LHSTy << RHSTy << LHS.get()->getSourceRange() - << RHS.get()->getSourceRange(); - incompatTy = S.Context.getPointerType(S.Context.VoidTy); - LHS = S.ImpCastExprToType(LHS.get(), incompatTy, CK_BitCast); - RHS = S.ImpCastExprToType(RHS.get(), incompatTy, CK_BitCast); - } + incompatTy = S.Context.getPointerType( + S.Context.getAddrSpaceQualType(S.Context.VoidTy, ResultAddrSpace)); + LHS = S.ImpCastExprToType(LHS.get(), incompatTy, LHSCastKind); + RHS = S.ImpCastExprToType(RHS.get(), incompatTy, RHSCastKind); + // FIXME: For OpenCL the warning emission and cast to void* leaves a room + // for casts between types with incompatible address space qualifiers. + // For the following code the compiler produces casts between global and + // local address spaces of the corresponded innermost pointees: + // local int *global *a; + // global int *global *b; + // a = (0 ? a : b); // see C99 6.5.16.1.p1. + S.Diag(Loc, diag::ext_typecheck_cond_incompatible_pointers) + << LHSTy << RHSTy << LHS.get()->getSourceRange() + << RHS.get()->getSourceRange(); return incompatTy; } // The pointer types are compatible. - QualType ResultTy = CompositeTy.withCVRQualifiers(MergedCVRQual); - auto LHSCastKind = CK_BitCast, RHSCastKind = CK_BitCast; + // In case of OpenCL ResultTy should have the address space qualifier + // which is a superset of address spaces of both the 2nd and the 3rd + // operands of the conditional operator. + QualType ResultTy = [&, ResultAddrSpace]() { + if (S.getLangOpts().OpenCL) { + Qualifiers CompositeQuals = CompositeTy.getQualifiers(); + CompositeQuals.setAddressSpace(ResultAddrSpace); + return S.Context + .getQualifiedType(CompositeTy.getUnqualifiedType(), CompositeQuals) + .withCVRQualifiers(MergedCVRQual); + } else + return CompositeTy.withCVRQualifiers(MergedCVRQual); + }(); if (IsBlockPointer) ResultTy = S.Context.getBlockPointerType(ResultTy); else { - // Cases 1a and 1b for OpenCL. - auto ResultAddrSpace = ResultTy.getQualifiers().getAddressSpace(); - LHSCastKind = lhQual.getAddressSpace() == ResultAddrSpace - ? CK_BitCast /* 1a */ - : CK_AddressSpaceConversion /* 1b */; - RHSCastKind = rhQual.getAddressSpace() == ResultAddrSpace - ? CK_BitCast /* 1a */ - : CK_AddressSpaceConversion /* 1b */; ResultTy = S.Context.getPointerType(ResultTy); } - // For case 1a of OpenCL, S.ImpCastExprToType will not insert bitcast - // if the target type does not change. LHS = S.ImpCastExprToType(LHS.get(), ResultTy, LHSCastKind); RHS = S.ImpCastExprToType(RHS.get(), ResultTy, RHSCastKind); return ResultTy; @@ -7378,10 +7399,31 @@ checkBlockPointerTypesForAssignment(Sema &S, QualType LHSType, Sema::AssignConvertType ConvTy = Sema::Compatible; // For blocks we enforce that qualifiers are identical. - if (lhptee.getLocalQualifiers() != rhptee.getLocalQualifiers()) + Qualifiers LQuals = lhptee.getLocalQualifiers(); + Qualifiers RQuals = rhptee.getLocalQualifiers(); + if (S.getLangOpts().OpenCL) { + LQuals.removeAddressSpace(); + RQuals.removeAddressSpace(); + } + if (LQuals != RQuals) ConvTy = Sema::CompatiblePointerDiscardsQualifiers; - if (!S.Context.typesAreBlockPointerCompatible(LHSType, RHSType)) + // FIXME: OpenCL doesn't define the exact compile time semantics for a block + // assignment. + // The current behavior is similar to C++ lambdas. A block might be + // assigned to a variable iff its return type and parameters are compatible + // (C99 6.2.7) with the corresponding return type and parameters of the LHS of + // an assignment. Presumably it should behave in way that a function pointer + // assignment does in C, so for each parameter and return type: + // * CVR and address space of LHS should be a superset of CVR and address + // space of RHS. + // * unqualified types should be compatible. + if (S.getLangOpts().OpenCL) { + if (!S.Context.typesAreBlockPointerCompatible( + S.Context.getQualifiedType(LHSType.getUnqualifiedType(), LQuals), + S.Context.getQualifiedType(RHSType.getUnqualifiedType(), RQuals))) + return Sema::IncompatibleBlockPointer; + } else if (!S.Context.typesAreBlockPointerCompatible(LHSType, RHSType)) return Sema::IncompatibleBlockPointer; return ConvTy; @@ -7603,7 +7645,12 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS, // U^ -> void* if (RHSType->getAs<BlockPointerType>()) { if (LHSPointer->getPointeeType()->isVoidType()) { - Kind = CK_BitCast; + unsigned AddrSpaceL = LHSPointer->getPointeeType().getAddressSpace(); + unsigned AddrSpaceR = RHSType->getAs<BlockPointerType>() + ->getPointeeType() + .getAddressSpace(); + Kind = + AddrSpaceL != AddrSpaceR ? CK_AddressSpaceConversion : CK_BitCast; return Compatible; } } @@ -7615,7 +7662,13 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS, if (isa<BlockPointerType>(LHSType)) { // U^ -> T^ if (RHSType->isBlockPointerType()) { - Kind = CK_BitCast; + unsigned AddrSpaceL = LHSType->getAs<BlockPointerType>() + ->getPointeeType() + .getAddressSpace(); + unsigned AddrSpaceR = RHSType->getAs<BlockPointerType>() + ->getPointeeType() + .getAddressSpace(); + Kind = AddrSpaceL != AddrSpaceR ? CK_AddressSpaceConversion : CK_BitCast; return checkBlockPointerTypesForAssignment(*this, LHSType, RHSType); } @@ -7648,7 +7701,7 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS, Kind = CK_BitCast; Sema::AssignConvertType result = checkObjCPointerTypesForAssignment(*this, LHSType, RHSType); - if (getLangOpts().ObjCAutoRefCount && + if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() && result == Compatible && !CheckObjCARCUnavailableWeakConversion(OrigLHSType, RHSType)) result = IncompatibleObjCWeakRef; @@ -7855,7 +7908,7 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &CallerRHS, if (RHS.isInvalid()) return Incompatible; Sema::AssignConvertType result = Compatible; - if (getLangOpts().ObjCAutoRefCount && + if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() && !CheckObjCARCUnavailableWeakConversion(LHSType, RHSType)) result = IncompatibleObjCWeakRef; return result; @@ -7932,9 +7985,9 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &CallerRHS, // Check for various Objective-C errors. If we are not reporting // diagnostics and just checking for errors, e.g., during overload // resolution, return Incompatible to indicate the failure. - if (getLangOpts().ObjCAutoRefCount && - CheckObjCARCConversion(SourceRange(), Ty, E, CCK_ImplicitConversion, - Diagnose, DiagnoseCFAudited) != ACR_okay) { + if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() && + CheckObjCConversion(SourceRange(), Ty, E, CCK_ImplicitConversion, + Diagnose, DiagnoseCFAudited) != ACR_okay) { if (!Diagnose) return Incompatible; } @@ -8094,7 +8147,7 @@ QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS, return RHSType; } - // FIXME: The code below also handles convertion between vectors and + // FIXME: The code below also handles conversion between vectors and // non-scalars, we should break this down into fine grained specific checks // and emit proper diagnostics. QualType VecType = LHSVecType ? LHSType : RHSType; @@ -9231,7 +9284,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, !(LHSType->isBlockPointerType() && IsRelational) && !LHS.get()->getLocStart().isMacroID() && !RHS.get()->getLocStart().isMacroID() && - ActiveTemplateInstantiations.empty()) { + !inTemplateInstantiation()) { // For non-floating point types, check for self-comparisons of the form // x == x, x != x, x < x, etc. These always evaluate to a constant, and // often indicate logic errors in the program. @@ -9374,7 +9427,10 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, // If both operands are pointers, [...] bring them to their composite // pointer type. if ((int)LHSType->isPointerType() + (int)RHSType->isPointerType() >= - (IsRelational ? 2 : 1)) { + (IsRelational ? 2 : 1) && + (!LangOpts.ObjCAutoRefCount || + !(LHSType->isObjCObjectPointerType() || + RHSType->isObjCObjectPointerType()))) { if (convertPointersToCompositeType(*this, Loc, LHS, RHS)) return QualType(); else @@ -9560,16 +9616,17 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, if (LHSIsNull && !RHSIsNull) { Expr *E = LHS.get(); if (getLangOpts().ObjCAutoRefCount) - CheckObjCARCConversion(SourceRange(), RHSType, E, CCK_ImplicitConversion); + CheckObjCConversion(SourceRange(), RHSType, E, + CCK_ImplicitConversion); LHS = ImpCastExprToType(E, RHSType, RPT ? CK_BitCast :CK_CPointerToObjCPointerCast); } else { Expr *E = RHS.get(); if (getLangOpts().ObjCAutoRefCount) - CheckObjCARCConversion(SourceRange(), LHSType, E, - CCK_ImplicitConversion, /*Diagnose=*/true, - /*DiagnoseCFAudited=*/false, Opc); + CheckObjCConversion(SourceRange(), LHSType, E, CCK_ImplicitConversion, + /*Diagnose=*/true, + /*DiagnoseCFAudited=*/false, Opc); RHS = ImpCastExprToType(E, LHSType, LPT ? CK_BitCast :CK_CPointerToObjCPointerCast); } @@ -9657,24 +9714,45 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, return InvalidOperands(Loc, LHS, RHS); } - -// Return a signed type that is of identical size and number of elements. -// For floating point vectors, return an integer type of identical size -// and number of elements. +// Return a signed ext_vector_type that is of identical size and number of +// elements. For floating point vectors, return an integer type of identical +// size and number of elements. In the non ext_vector_type case, search from +// the largest type to the smallest type to avoid cases where long long == long, +// where long gets picked over long long. QualType Sema::GetSignedVectorType(QualType V) { const VectorType *VTy = V->getAs<VectorType>(); unsigned TypeSize = Context.getTypeSize(VTy->getElementType()); - if (TypeSize == Context.getTypeSize(Context.CharTy)) - return Context.getExtVectorType(Context.CharTy, VTy->getNumElements()); - else if (TypeSize == Context.getTypeSize(Context.ShortTy)) - return Context.getExtVectorType(Context.ShortTy, VTy->getNumElements()); - else if (TypeSize == Context.getTypeSize(Context.IntTy)) - return Context.getExtVectorType(Context.IntTy, VTy->getNumElements()); + + if (isa<ExtVectorType>(VTy)) { + if (TypeSize == Context.getTypeSize(Context.CharTy)) + return Context.getExtVectorType(Context.CharTy, VTy->getNumElements()); + else if (TypeSize == Context.getTypeSize(Context.ShortTy)) + return Context.getExtVectorType(Context.ShortTy, VTy->getNumElements()); + else if (TypeSize == Context.getTypeSize(Context.IntTy)) + return Context.getExtVectorType(Context.IntTy, VTy->getNumElements()); + else if (TypeSize == Context.getTypeSize(Context.LongTy)) + return Context.getExtVectorType(Context.LongTy, VTy->getNumElements()); + assert(TypeSize == Context.getTypeSize(Context.LongLongTy) && + "Unhandled vector element size in vector compare"); + return Context.getExtVectorType(Context.LongLongTy, VTy->getNumElements()); + } + + if (TypeSize == Context.getTypeSize(Context.LongLongTy)) + return Context.getVectorType(Context.LongLongTy, VTy->getNumElements(), + VectorType::GenericVector); else if (TypeSize == Context.getTypeSize(Context.LongTy)) - return Context.getExtVectorType(Context.LongTy, VTy->getNumElements()); - assert(TypeSize == Context.getTypeSize(Context.LongLongTy) && + return Context.getVectorType(Context.LongTy, VTy->getNumElements(), + VectorType::GenericVector); + else if (TypeSize == Context.getTypeSize(Context.IntTy)) + return Context.getVectorType(Context.IntTy, VTy->getNumElements(), + VectorType::GenericVector); + else if (TypeSize == Context.getTypeSize(Context.ShortTy)) + return Context.getVectorType(Context.ShortTy, VTy->getNumElements(), + VectorType::GenericVector); + assert(TypeSize == Context.getTypeSize(Context.CharTy) && "Unhandled vector element size in vector compare"); - return Context.getExtVectorType(Context.LongLongTy, VTy->getNumElements()); + return Context.getVectorType(Context.CharTy, VTy->getNumElements(), + VectorType::GenericVector); } /// CheckVectorCompareOperands - vector comparisons are a clang extension that @@ -9703,8 +9781,7 @@ QualType Sema::CheckVectorCompareOperands(ExprResult &LHS, ExprResult &RHS, // For non-floating point types, check for self-comparisons of the form // x == x, x != x, x < x, etc. These always evaluate to a constant, and // often indicate logic errors in the program. - if (!LHSType->hasFloatingRepresentation() && - ActiveTemplateInstantiations.empty()) { + if (!LHSType->hasFloatingRepresentation() && !inTemplateInstantiation()) { if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(LHS.get()->IgnoreParenImpCasts())) if (DeclRefExpr* DRR @@ -9722,7 +9799,7 @@ QualType Sema::CheckVectorCompareOperands(ExprResult &LHS, ExprResult &RHS, assert (RHS.get()->getType()->hasFloatingRepresentation()); CheckFloatComparison(Loc, LHS.get(), RHS.get()); } - + // Return a signed type for the vector. return GetSignedVectorType(vType); } @@ -9739,7 +9816,7 @@ QualType Sema::CheckVectorLogicalOperands(ExprResult &LHS, ExprResult &RHS, if (getLangOpts().OpenCL && getLangOpts().OpenCLVersion < 120 && vType->hasFloatingRepresentation()) return InvalidOperands(Loc, LHS, RHS); - + return GetSignedVectorType(LHS.get()->getType()); } @@ -9792,7 +9869,7 @@ inline QualType Sema::CheckLogicalOperands(ExprResult &LHS, ExprResult &RHS, !LHS.get()->getType()->isBooleanType() && RHS.get()->getType()->isIntegerType() && !RHS.get()->isValueDependent() && // Don't warn in macros or template instantiations. - !Loc.isMacroID() && ActiveTemplateInstantiations.empty()) { + !Loc.isMacroID() && !inTemplateInstantiation()) { // If the RHS can be constant folded, and if it constant folds to something // that isn't 0 or 1 (which indicate a potential logical operation that // happened to fold to true/false) then warn. @@ -10268,7 +10345,10 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS, const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(InnerLHS); if (!DRE || DRE->getDecl()->hasAttr<BlocksAttr>()) checkRetainCycles(LHSExpr, RHS.get()); + } + if (LHSType.getObjCLifetime() == Qualifiers::OCL_Strong || + LHSType.isNonWeakInMRRWithObjCWeak(Context)) { // It is safe to assign a weak reference into a strong variable. // Although this code can still have problems: // id x = self.weakProp; @@ -10276,11 +10356,13 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS, // we do not warn to warn spuriously when 'x' and 'y' are on separate // paths through the function. This should be revisited if // -Wrepeated-use-of-weak is made flow-sensitive. + // For ObjCWeak only, we do not warn if the assign is to a non-weak + // variable, which will be valid for the current autorelease scope. if (!Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, RHS.get()->getLocStart())) getCurFunction()->markSafeWeakUse(RHS.get()); - } else if (getLangOpts().ObjCAutoRefCount) { + } else if (getLangOpts().ObjCAutoRefCount || getLangOpts().ObjCWeak) { checkUnsafeExprAssigns(Loc, LHSExpr, RHS.get()); } } @@ -10328,7 +10410,7 @@ void Sema::DiagnoseCommaOperator(const Expr *LHS, SourceLocation Loc) { return; // Don't warn in template instantiations. - if (!ActiveTemplateInstantiations.empty()) + if (inTemplateInstantiation()) return; // Scope isn't fine-grained enough to whitelist the specific cases, so @@ -10923,7 +11005,7 @@ static inline UnaryOperatorKind ConvertTokenKindToUnaryOpcode( /// suppressed in the event of macro expansions. static void DiagnoseSelfAssignment(Sema &S, Expr *LHSExpr, Expr *RHSExpr, SourceLocation OpLoc) { - if (!S.ActiveTemplateInstantiations.empty()) + if (S.inTemplateInstantiation()) return; if (OpLoc.isInvalid() || OpLoc.isMacroID()) return; @@ -11063,7 +11145,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, if (LHSTy->isAtomicType() || RHSTy->isAtomicType()) { SourceRange SR(LHSExpr->getLocStart(), RHSExpr->getLocEnd()); if (BO_Assign == Opc) - Diag(OpLoc, diag::err_atomic_init_constant) << SR; + Diag(OpLoc, diag::err_opencl_atomic_init) << 0 << SR; else ResultTy = InvalidOperands(OpLoc, LHS, RHS); return ExprError(); @@ -11212,7 +11294,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, if (CompResultTy.isNull()) return new (Context) BinaryOperator(LHS.get(), RHS.get(), Opc, ResultTy, VK, - OK, OpLoc, FPFeatures.fp_contract); + OK, OpLoc, FPFeatures); if (getLangOpts().CPlusPlus && LHS.get()->getObjectKind() != OK_ObjCProperty) { VK = VK_LValue; @@ -11220,7 +11302,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, } return new (Context) CompoundAssignOperator( LHS.get(), RHS.get(), Opc, ResultTy, VK, OK, CompLHSTy, CompResultTy, - OpLoc, FPFeatures.fp_contract); + OpLoc, FPFeatures); } /// DiagnoseBitwisePrecedence - Emit a warning when bitwise and comparison @@ -11659,7 +11741,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, Context.getLangOpts().OpenCLVersion < 120) { // OpenCL v1.1 6.3.h: The logical operator not (!) does not // operate on scalar float types. - if (!resultType->isIntegerType()) + if (!resultType->isIntegerType() && !resultType->isPointerType()) return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) << resultType << Input.get()->getSourceRange()); } @@ -12193,7 +12275,8 @@ void Sema::ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope) { // Enter a new evaluation context to insulate the block from any // cleanups from the enclosing full-expression. - PushExpressionEvaluationContext(PotentiallyEvaluated); + PushExpressionEvaluationContext( + ExpressionEvaluationContext::PotentiallyEvaluated); } void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo, @@ -13086,7 +13169,7 @@ void Sema::PopExpressionEvaluationContext() { unsigned NumTypos = Rec.NumTypos; if (!Rec.Lambdas.empty()) { - if (Rec.isUnevaluated() || Rec.Context == ConstantEvaluated) { + if (Rec.isUnevaluated() || Rec.isConstantEvaluated()) { unsigned D; if (Rec.isUnevaluated()) { // C++11 [expr.prim.lambda]p2: @@ -13107,7 +13190,7 @@ void Sema::PopExpressionEvaluationContext() { // are part of function-signatures. Be mindful that P0315 (Lambdas in // unevaluated contexts) might lift some of these restrictions in a // future version. - if (Rec.Context != ConstantEvaluated || !getLangOpts().CPlusPlus1z) + if (!Rec.isConstantEvaluated() || !getLangOpts().CPlusPlus1z) for (const auto *L : Rec.Lambdas) Diag(L->getLocStart(), D); } else { @@ -13124,7 +13207,7 @@ void Sema::PopExpressionEvaluationContext() { // temporaries that we may have created as part of the evaluation of // the expression in that context: they aren't relevant because they // will never be constructed. - if (Rec.isUnevaluated() || Rec.Context == ConstantEvaluated) { + if (Rec.isUnevaluated() || Rec.isConstantEvaluated()) { ExprCleanupObjects.erase(ExprCleanupObjects.begin() + Rec.NumCleanupObjects, ExprCleanupObjects.end()); Cleanup = Rec.ParentCleanup; @@ -13166,19 +13249,19 @@ ExprResult Sema::HandleExprEvaluationContextForTypeof(Expr *E) { /// captured by C++'s idea of an "unevaluated context". static bool isEvaluatableContext(Sema &SemaRef) { switch (SemaRef.ExprEvalContexts.back().Context) { - case Sema::Unevaluated: - case Sema::UnevaluatedAbstract: - case Sema::DiscardedStatement: + case Sema::ExpressionEvaluationContext::Unevaluated: + case Sema::ExpressionEvaluationContext::UnevaluatedAbstract: + case Sema::ExpressionEvaluationContext::DiscardedStatement: // Expressions in this context are never evaluated. return false; - case Sema::UnevaluatedList: - case Sema::ConstantEvaluated: - case Sema::PotentiallyEvaluated: + case Sema::ExpressionEvaluationContext::UnevaluatedList: + case Sema::ExpressionEvaluationContext::ConstantEvaluated: + case Sema::ExpressionEvaluationContext::PotentiallyEvaluated: // Expressions in this context could be evaluated. return true; - case Sema::PotentiallyEvaluatedIfUsed: + case Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed: // Referenced declarations will only be used if the construct in the // containing expression is used, at which point we'll be given another // turn to mark them. @@ -13196,17 +13279,17 @@ static bool isOdrUseContext(Sema &SemaRef, bool SkipDependentUses = true) { return false; switch (SemaRef.ExprEvalContexts.back().Context) { - case Sema::Unevaluated: - case Sema::UnevaluatedList: - case Sema::UnevaluatedAbstract: - case Sema::DiscardedStatement: + case Sema::ExpressionEvaluationContext::Unevaluated: + case Sema::ExpressionEvaluationContext::UnevaluatedList: + case Sema::ExpressionEvaluationContext::UnevaluatedAbstract: + case Sema::ExpressionEvaluationContext::DiscardedStatement: return false; - case Sema::ConstantEvaluated: - case Sema::PotentiallyEvaluated: + case Sema::ExpressionEvaluationContext::ConstantEvaluated: + case Sema::ExpressionEvaluationContext::PotentiallyEvaluated: return true; - case Sema::PotentiallyEvaluatedIfUsed: + case Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed: return false; } llvm_unreachable("Invalid context"); @@ -13357,7 +13440,7 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, if (!AlreadyInstantiated || Func->isConstexpr()) { if (isa<CXXRecordDecl>(Func->getDeclContext()) && cast<CXXRecordDecl>(Func->getDeclContext())->isLocalClass() && - ActiveTemplateInstantiations.size()) + CodeSynthesisContexts.size()) PendingLocalImplicitInstantiations.push_back( std::make_pair(Func, PointOfInstantiation)); else if (Func->isConstexpr()) @@ -13540,6 +13623,13 @@ static bool isVariableCapturable(CapturingScopeInfo *CSI, VarDecl *Var, } return false; } + // OpenCL v2.0 s6.12.5: Blocks cannot reference/capture other blocks + if (S.getLangOpts().OpenCL && IsBlock && + Var->getType()->isBlockPointerType()) { + if (Diagnose) + S.Diag(Loc, diag::err_opencl_block_ref_block); + return false; + } return true; } @@ -13577,16 +13667,55 @@ static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var, } // Warn about implicitly autoreleasing indirect parameters captured by blocks. - if (auto *PT = dyn_cast<PointerType>(CaptureType)) { + if (const auto *PT = CaptureType->getAs<PointerType>()) { + // This function finds out whether there is an AttributedType of kind + // attr_objc_ownership in Ty. The existence of AttributedType of kind + // attr_objc_ownership implies __autoreleasing was explicitly specified + // rather than being added implicitly by the compiler. + auto IsObjCOwnershipAttributedType = [](QualType Ty) { + while (const auto *AttrTy = Ty->getAs<AttributedType>()) { + if (AttrTy->getAttrKind() == AttributedType::attr_objc_ownership) + return true; + + // Peel off AttributedTypes that are not of kind objc_ownership. + Ty = AttrTy->getModifiedType(); + } + + return false; + }; + QualType PointeeTy = PT->getPointeeType(); - if (isa<ObjCObjectPointerType>(PointeeTy.getCanonicalType()) && + + if (PointeeTy->getAs<ObjCObjectPointerType>() && PointeeTy.getObjCLifetime() == Qualifiers::OCL_Autoreleasing && - !isa<AttributedType>(PointeeTy)) { + !IsObjCOwnershipAttributedType(PointeeTy)) { if (BuildAndDiagnose) { SourceLocation VarLoc = Var->getLocation(); S.Diag(Loc, diag::warn_block_capture_autoreleasing); - S.Diag(VarLoc, diag::note_declare_parameter_autoreleasing) << - FixItHint::CreateInsertion(VarLoc, "__autoreleasing"); + { + auto AddAutoreleaseNote = + S.Diag(VarLoc, diag::note_declare_parameter_autoreleasing); + // Provide a fix-it for the '__autoreleasing' keyword at the + // appropriate location in the variable's type. + if (const auto *TSI = Var->getTypeSourceInfo()) { + PointerTypeLoc PTL = + TSI->getTypeLoc().getAsAdjusted<PointerTypeLoc>(); + if (PTL) { + SourceLocation Loc = PTL.getPointeeLoc().getEndLoc(); + Loc = Lexer::getLocForEndOfToken(Loc, 0, S.getSourceManager(), + S.getLangOpts()); + if (Loc.isValid()) { + StringRef CharAtLoc = Lexer::getSourceText( + CharSourceRange::getCharRange(Loc, Loc.getLocWithOffset(1)), + S.getSourceManager(), S.getLangOpts()); + AddAutoreleaseNote << FixItHint::CreateInsertion( + Loc, CharAtLoc.empty() || !isWhitespace(CharAtLoc[0]) + ? " __autoreleasing " + : " __autoreleasing"); + } + } + } + } S.Diag(VarLoc, diag::note_declare_parameter_strong); } } @@ -13615,7 +13744,8 @@ static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var, // Enter a new evaluation context to insulate the copy // full-expression. - EnterExpressionEvaluationContext scope(S, S.PotentiallyEvaluated); + EnterExpressionEvaluationContext scope( + S, Sema::ExpressionEvaluationContext::PotentiallyEvaluated); // According to the blocks spec, the capture of a variable from // the stack requires a const copy constructor. This is not true @@ -13898,8 +14028,10 @@ bool Sema::tryCaptureVariable( // Check whether we've already captured it. if (isVariableAlreadyCapturedInScopeInfo(CSI, Var, Nested, CaptureType, - DeclRefType)) + DeclRefType)) { + CSI->getCapture(Var).markUsed(BuildAndDiagnose); break; + } // If we are instantiating a generic lambda call operator body, // we do not want to capture new variables. What was captured // during either a lambdas transformation or initial parsing @@ -14227,8 +14359,9 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc, (SemaRef.CurContext != Var->getDeclContext() && Var->getDeclContext()->isFunctionOrMethod() && Var->hasLocalStorage()); if (RefersToEnclosingScope) { - if (LambdaScopeInfo *const LSI = - SemaRef.getCurLambda(/*IgnoreCapturedRegions=*/true)) { + LambdaScopeInfo *const LSI = + SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true); + if (LSI && !LSI->CallOperator->Encloses(Var->getDeclContext())) { // If a variable could potentially be odr-used, defer marking it so // until we finish analyzing the full expression for any // lvalue-to-rvalue @@ -14363,7 +14496,8 @@ bool MarkReferencedDecls::TraverseTemplateArgument( const TemplateArgument &Arg) { { // A non-type template argument is a constant-evaluated context. - EnterExpressionEvaluationContext Evaluated(S, Sema::ConstantEvaluated); + EnterExpressionEvaluationContext Evaluated( + S, Sema::ExpressionEvaluationContext::ConstantEvaluated); if (Arg.getKind() == TemplateArgument::Declaration) { if (Decl *D = Arg.getAsDecl()) S.MarkAnyDeclReferenced(Loc, D, true); @@ -14483,19 +14617,19 @@ void Sema::MarkDeclarationsReferencedInExpr(Expr *E, bool Sema::DiagRuntimeBehavior(SourceLocation Loc, const Stmt *Statement, const PartialDiagnostic &PD) { switch (ExprEvalContexts.back().Context) { - case Unevaluated: - case UnevaluatedList: - case UnevaluatedAbstract: - case DiscardedStatement: + case ExpressionEvaluationContext::Unevaluated: + case ExpressionEvaluationContext::UnevaluatedList: + case ExpressionEvaluationContext::UnevaluatedAbstract: + case ExpressionEvaluationContext::DiscardedStatement: // The argument will never be evaluated, so don't complain. break; - case ConstantEvaluated: + case ExpressionEvaluationContext::ConstantEvaluated: // Relevant diagnostics should be produced by constant evaluation. break; - case PotentiallyEvaluated: - case PotentiallyEvaluatedIfUsed: + case ExpressionEvaluationContext::PotentiallyEvaluated: + case ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed: if (Statement && getCurFunctionOrMethodDecl()) { FunctionScopes.back()->PossiblyUnreachableDiags. push_back(sema::PossiblyUnreachableDiag(PD, Loc, Statement)); |