aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaExpr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaExpr.cpp')
-rw-r--r--lib/Sema/SemaExpr.cpp450
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));