forked from OSchip/llvm-project
Perform the bad-address-space conversions check as part of
CheckPointerTypesForAssignment. llvm-svn: 124632
This commit is contained in:
parent
c1dfd93e1e
commit
4fff8f6cff
|
@ -1007,9 +1007,6 @@ def err_attribute_address_space_too_high : Error<
|
|||
"address space is larger than the maximum supported (%0)">;
|
||||
def err_attribute_address_multiple_qualifiers : Error<
|
||||
"multiple address spaces specified for type">;
|
||||
def err_implicit_pointer_address_space_cast : Error<
|
||||
"illegal implicit conversion between two pointers with different address "
|
||||
"spaces">;
|
||||
def err_as_qualified_auto_decl : Error<
|
||||
"automatic variable qualified with an address space">;
|
||||
def err_arg_with_address_space : Error<
|
||||
|
@ -2941,7 +2938,15 @@ def err_typecheck_convert_incompatible_block_pointer : Error<
|
|||
" %0 "
|
||||
"%select{from|to parameter of type|from a function with result type|to type|"
|
||||
"with an expression of type|to parameter of type|to type}2 %1">;
|
||||
|
||||
def err_typecheck_incompatible_address_space : Error<
|
||||
"%select{assigning %1 to %0"
|
||||
"|passing %0 to parameter of type %1"
|
||||
"|returning %0 from a function with result type %1"
|
||||
"|converting %0 to type %1"
|
||||
"|initializing %0 with an expression of type %1"
|
||||
"|sending %0 to parameter of type %1"
|
||||
"|casting %0 to type %1}2"
|
||||
" changes address space of pointer">;
|
||||
def err_typecheck_convert_ambiguous : Error<
|
||||
"ambiguity in initializing value of type %0 with initializer of type %1">;
|
||||
def err_cannot_initialize_decl_noname : Error<
|
||||
|
|
|
@ -4512,6 +4512,11 @@ public:
|
|||
/// c/v/r qualifiers, which we accept as an extension.
|
||||
CompatiblePointerDiscardsQualifiers,
|
||||
|
||||
/// IncompatiblePointerDiscardsQualifiers - The assignment
|
||||
/// discards qualifiers that we don't permit to be discarded,
|
||||
/// like address spaces.
|
||||
IncompatiblePointerDiscardsQualifiers,
|
||||
|
||||
/// IncompatibleNestedPointerQualifiers - The assignment is between two
|
||||
/// nested pointer types, and the qualifiers other than the first two
|
||||
/// levels differ e.g. char ** -> const char **, but we accept them as an
|
||||
|
|
|
@ -206,15 +206,6 @@ void Sema::ImpCastExprToType(Expr *&Expr, QualType Ty,
|
|||
if (ExprTy == TypeTy)
|
||||
return;
|
||||
|
||||
if (Expr->getType()->isPointerType() && Ty->isPointerType()) {
|
||||
QualType ExprBaseType = cast<PointerType>(ExprTy)->getPointeeType();
|
||||
QualType BaseType = cast<PointerType>(TypeTy)->getPointeeType();
|
||||
if (ExprBaseType.getAddressSpace() != BaseType.getAddressSpace()) {
|
||||
Diag(Expr->getExprLoc(), diag::err_implicit_pointer_address_space_cast)
|
||||
<< Expr->getSourceRange();
|
||||
}
|
||||
}
|
||||
|
||||
// If this is a derived-to-base cast to a through a virtual base, we
|
||||
// need a vtable.
|
||||
if (Kind == CK_DerivedToBase &&
|
||||
|
|
|
@ -5356,20 +5356,28 @@ checkPointerTypesForAssignment(Sema &S, QualType lhsType, QualType rhsType) {
|
|||
assert(lhsType.isCanonical() && "LHS not canonicalized!");
|
||||
assert(rhsType.isCanonical() && "RHS not canonicalized!");
|
||||
|
||||
QualType lhptee, rhptee;
|
||||
|
||||
// get the "pointed to" type (ignoring qualifiers at the top level)
|
||||
lhptee = lhsType->getAs<PointerType>()->getPointeeType();
|
||||
rhptee = rhsType->getAs<PointerType>()->getPointeeType();
|
||||
const Type *lhptee, *rhptee;
|
||||
Qualifiers lhq, rhq;
|
||||
llvm::tie(lhptee, lhq) = cast<PointerType>(lhsType)->getPointeeType().split();
|
||||
llvm::tie(rhptee, rhq) = cast<PointerType>(rhsType)->getPointeeType().split();
|
||||
|
||||
Sema::AssignConvertType ConvTy = Sema::Compatible;
|
||||
|
||||
// C99 6.5.16.1p1: This following citation is common to constraints
|
||||
// 3 & 4 (below). ...and the type *pointed to* by the left has all the
|
||||
// qualifiers of the type *pointed to* by the right;
|
||||
// FIXME: Handle ExtQualType
|
||||
if (!lhptee.isAtLeastAsQualifiedAs(rhptee))
|
||||
ConvTy = Sema::CompatiblePointerDiscardsQualifiers;
|
||||
Qualifiers lq;
|
||||
|
||||
if (!lhq.compatiblyIncludes(rhq)) {
|
||||
// Treat address-space mismatches as fatal. TODO: address subspaces
|
||||
if (lhq.getAddressSpace() != rhq.getAddressSpace())
|
||||
ConvTy = Sema::IncompatiblePointerDiscardsQualifiers;
|
||||
|
||||
// For GCC compatibility, other qualifier mismatches are treated
|
||||
// as still compatible in C.
|
||||
else ConvTy = Sema::CompatiblePointerDiscardsQualifiers;
|
||||
}
|
||||
|
||||
// C99 6.5.16.1p1 (constraint 4): If one operand is a pointer to an object or
|
||||
// incomplete type and the other is a pointer to a qualified or unqualified
|
||||
|
@ -5391,30 +5399,31 @@ checkPointerTypesForAssignment(Sema &S, QualType lhsType, QualType rhsType) {
|
|||
assert(lhptee->isFunctionType());
|
||||
return Sema::FunctionVoidPointer;
|
||||
}
|
||||
|
||||
// C99 6.5.16.1p1 (constraint 3): both operands are pointers to qualified or
|
||||
// unqualified versions of compatible types, ...
|
||||
lhptee = lhptee.getUnqualifiedType();
|
||||
rhptee = rhptee.getUnqualifiedType();
|
||||
if (!S.Context.typesAreCompatible(lhptee, rhptee)) {
|
||||
QualType ltrans = QualType(lhptee, 0), rtrans = QualType(rhptee, 0);
|
||||
if (!S.Context.typesAreCompatible(ltrans, rtrans)) {
|
||||
// Check if the pointee types are compatible ignoring the sign.
|
||||
// We explicitly check for char so that we catch "char" vs
|
||||
// "unsigned char" on systems where "char" is unsigned.
|
||||
if (lhptee->isCharType())
|
||||
lhptee = S.Context.UnsignedCharTy;
|
||||
ltrans = S.Context.UnsignedCharTy;
|
||||
else if (lhptee->hasSignedIntegerRepresentation())
|
||||
lhptee = S.Context.getCorrespondingUnsignedType(lhptee);
|
||||
ltrans = S.Context.getCorrespondingUnsignedType(ltrans);
|
||||
|
||||
if (rhptee->isCharType())
|
||||
rhptee = S.Context.UnsignedCharTy;
|
||||
rtrans = S.Context.UnsignedCharTy;
|
||||
else if (rhptee->hasSignedIntegerRepresentation())
|
||||
rhptee = S.Context.getCorrespondingUnsignedType(rhptee);
|
||||
rtrans = S.Context.getCorrespondingUnsignedType(rtrans);
|
||||
|
||||
if (lhptee == rhptee) {
|
||||
if (ltrans == rtrans) {
|
||||
// Types are compatible ignoring the sign. Qualifier incompatibility
|
||||
// takes priority over sign incompatibility because the sign
|
||||
// warning can be disabled.
|
||||
if (ConvTy != Sema::Compatible)
|
||||
return ConvTy;
|
||||
|
||||
return Sema::IncompatiblePointerSign;
|
||||
}
|
||||
|
||||
|
@ -5424,11 +5433,11 @@ checkPointerTypesForAssignment(Sema &S, QualType lhsType, QualType rhsType) {
|
|||
// level of indirection, this must be the issue.
|
||||
if (isa<PointerType>(lhptee) && isa<PointerType>(rhptee)) {
|
||||
do {
|
||||
lhptee = cast<PointerType>(lhptee)->getPointeeType();
|
||||
rhptee = cast<PointerType>(rhptee)->getPointeeType();
|
||||
lhptee = cast<PointerType>(lhptee)->getPointeeType().getTypePtr();
|
||||
rhptee = cast<PointerType>(rhptee)->getPointeeType().getTypePtr();
|
||||
} while (isa<PointerType>(lhptee) && isa<PointerType>(rhptee));
|
||||
|
||||
if (S.Context.hasSameUnqualifiedType(lhptee, rhptee))
|
||||
if (lhptee == rhptee)
|
||||
return Sema::IncompatibleNestedPointerQualifiers;
|
||||
}
|
||||
|
||||
|
@ -8680,6 +8689,17 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
|
|||
case FunctionVoidPointer:
|
||||
DiagKind = diag::ext_typecheck_convert_pointer_void_func;
|
||||
break;
|
||||
case IncompatiblePointerDiscardsQualifiers: {
|
||||
Qualifiers lhq = SrcType->getPointeeType().getQualifiers();
|
||||
Qualifiers rhq = DstType->getPointeeType().getQualifiers();
|
||||
if (lhq.getAddressSpace() != rhq.getAddressSpace()) {
|
||||
DiagKind = diag::err_typecheck_incompatible_address_space;
|
||||
break;
|
||||
}
|
||||
|
||||
llvm_unreachable("unknown error case for discarding qualifiers!");
|
||||
// fallthrough
|
||||
}
|
||||
case CompatiblePointerDiscardsQualifiers:
|
||||
// If the qualifiers lost were because we were applying the
|
||||
// (deprecated) C++ conversion from a string literal to a char*
|
||||
|
|
|
@ -11,8 +11,7 @@ INT int_value;
|
|||
__attribute__((address_space(1))) int int_as_one;
|
||||
|
||||
// TYPE_EXT_QUAL
|
||||
ASInt *as_int_ptr1 = &int_value; // expected-error{{different address spaces}} \
|
||||
// FIXME: expected-warning{{discards qualifiers}}
|
||||
ASInt *as_int_ptr1 = &int_value; // expected-error{{changes address space of pointer}}
|
||||
ASInt *as_int_ptr2 = &int_as_one;
|
||||
|
||||
// FIXME: TYPE_FIXED_WIDTH_INT
|
||||
|
|
|
@ -36,7 +36,6 @@ struct _st {
|
|||
// rdar://6774906
|
||||
__attribute__((address_space(256))) void * * const base = 0;
|
||||
void * get_0(void) {
|
||||
return base[0]; // expected-error {{illegal implicit conversion between two pointers with different address spaces}} \
|
||||
expected-warning {{returning '__attribute__((address_space(256))) void *' from a function with result type 'void *' discards qualifiers}}
|
||||
return base[0]; // expected-error {{returning '__attribute__((address_space(256))) void *' from a function with result type 'void *' changes address space of pointer}}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue