// Type Operators
//===--------------------------------------------------------------------===//
+ /// getArrayDecayedType - Return the properly qualified result of decaying the
+ /// specified array type to a pointer. This operation is non-trivial when
+ /// handling typedefs etc. The canonical type of "T" must be an array type,
+ /// this returns a pointer to a properly qualified element of the array.
+ ///
+ /// See C99 6.7.5.3p7 and C99 6.3.2.1p3.
+ QualType getArrayDecayedType(QualType T);
+
/// maxIntegerType - Returns the highest ranked integer type. Handles 3
/// different type combos: unsigned/unsigned, signed/signed, signed/unsigned.
static QualType maxIntegerType(QualType lhs, QualType rhs);
return IntTy;
}
+//===----------------------------------------------------------------------===//
+// Type Operators
+//===----------------------------------------------------------------------===//
+
+/// getArrayDecayedType - Return the properly qualified result of decaying the
+/// specified array type to a pointer. This operation is non-trivial when
+/// handling typedefs etc. The canonical type of "T" must be an array type,
+/// this returns a pointer to a properly qualified element of the array.
+///
+/// See C99 6.7.5.3p7 and C99 6.3.2.1p3.
+QualType ASTContext::getArrayDecayedType(QualType Ty) {
+ // Handle the common case where typedefs are not involved directly.
+ QualType EltTy;
+ unsigned ArrayQuals = 0;
+ unsigned PointerQuals = 0;
+ if (ArrayType *AT = dyn_cast<ArrayType>(Ty)) {
+ // Since T "isa" an array type, it could not have had an address space
+ // qualifier, just CVR qualifiers. The properly qualified element pointer
+ // gets the union of the CVR qualifiers from the element and the array, and
+ // keeps any address space qualifier on the element type if present.
+ EltTy = AT->getElementType();
+ ArrayQuals = Ty.getCVRQualifiers();
+ PointerQuals = AT->getIndexTypeQualifier();
+ } else {
+ // Otherwise, we have an ASQualType or a typedef, etc. Make sure we don't
+ // lose qualifiers when dealing with typedefs. Example:
+ // typedef int arr[10];
+ // void test2() {
+ // const arr b;
+ // b[4] = 1;
+ // }
+ //
+ // The decayed type of b is "const int*" even though the element type of the
+ // array is "int".
+ QualType CanTy = Ty.getCanonicalType();
+ const ArrayType *PrettyArrayType = Ty->getAsArrayType();
+ assert(PrettyArrayType && "Not an array type!");
+
+ // Get the element type with 'getAsArrayType' so that we don't lose any
+ // typedefs in the element type of the array.
+ EltTy = PrettyArrayType->getElementType();
+
+ // If the array was address-space qualifier, make sure to ASQual the element
+ // type. We can just grab the address space from the canonical type.
+ if (unsigned AS = CanTy.getAddressSpace())
+ EltTy = getASQualType(EltTy, AS);
+
+ // To properly handle [multiple levels of] typedefs, typeof's etc, we take
+ // the CVR qualifiers directly from the canonical type, which is guaranteed
+ // to have the full set unioned together.
+ ArrayQuals = CanTy.getCVRQualifiers();
+ PointerQuals = PrettyArrayType->getIndexTypeQualifier();
+ }
+
+ // Apply any CVR qualifiers from the array type.
+ EltTy = EltTy.getQualifiedType(ArrayQuals | EltTy.getCVRQualifiers());
+
+ QualType PtrTy = getPointerType(EltTy);
+
+ // int x[restrict 4] -> int *restrict
+ PtrTy = PtrTy.getQualifiedType(PointerQuals);
+
+ return PtrTy;
+}
+
/// getIntegerRank - Return an integer conversion rank (C99 6.3.1.1p1). This
/// routine will assert if passed a built-in type that isn't an integer or enum.
static int getIntegerRank(QualType t) {
// we need to consider storing both types (in ParmVarDecl)...
//
QualType parmDeclType = QualType::getFromOpaquePtr(PI.TypeInfo);
- if (const ArrayType *AT = parmDeclType->getAsArrayType()) {
+ if (parmDeclType->isArrayType()) {
// int x[restrict 4] -> int *restrict
- parmDeclType = Context.getPointerType(AT->getElementType());
- parmDeclType = parmDeclType.getQualifiedType(AT->getIndexTypeQualifier());
+ parmDeclType = Context.getArrayDecayedType(parmDeclType);
} else if (parmDeclType->isFunctionType())
parmDeclType = Context.getPointerType(parmDeclType);
}
if (Ty->isFunctionType())
ImpCastExprToType(E, Context.getPointerType(Ty));
- else if (const ArrayType *ArrayTy = Ty->getAsArrayType()) {
- // Make sure we don't lose qualifiers when dealing with typedefs. Example:
- // typedef int arr[10];
- // void test2() {
- // const arr b;
- // b[4] = 1;
- // }
- QualType ELT = ArrayTy->getElementType();
- // FIXME: Handle ASQualType
- ELT = ELT.getQualifiedType(Ty.getCVRQualifiers()|ELT.getCVRQualifiers());
- ImpCastExprToType(E, Context.getPointerType(ELT));
- }
+ else if (Ty->isArrayType())
+ ImpCastExprToType(E, Context.getArrayDecayedType(Ty));
}
/// UsualUnaryConversions - Performs various conversions that are common to most
// type in ParmVarDecl (which makes the code generator unhappy).
//
// FIXME: We still apparently need the conversion in
- // Sema::ParseParamDeclarator(). This doesn't make any sense, since
+ // Sema::ActOnParamDeclarator(). This doesn't make any sense, since
// it should be driving off the type being created here.
//
// FIXME: If a source translation tool needs to see the original type,
// then we need to consider storing both types somewhere...
//
- if (const ArrayType *AT = ArgTy->getAsArrayType()) {
- // int x[restrict 4] -> int *restrict
- ArgTy = Context.getPointerType(AT->getElementType());
- ArgTy = ArgTy.getQualifiedType(AT->getIndexTypeQualifier());
+ if (ArgTy->isArrayType()) {
+ ArgTy = Context.getArrayDecayedType(ArgTy);
} else if (ArgTy->isFunctionType())
ArgTy = Context.getPointerType(ArgTy);
+
// Look for 'void'. void is allowed only as a single argument to a
// function with no other parameters (C99 6.7.5.3p10). We record
// int(void) as a FunctionTypeProto with an empty argument list.
assert(!ArgTy.isNull() && "Couldn't parse type?");
// Perform the default function/array conversion (C99 6.7.5.3p[7,8]).
// This matches the conversion that is done in
- // Sema::ParseParamDeclarator().
- if (const ArrayType *AT = ArgTy->getAsArrayType())
- ArgTy = Context.getPointerType(AT->getElementType());
+ // Sema::ActOnParamDeclarator().
+ if (ArgTy->isArrayType())
+ ArgTy = Context.getArrayDecayedType(ArgTy);
else if (ArgTy->isFunctionType())
ArgTy = Context.getPointerType(ArgTy);
ArgTys.push_back(ArgTy);
-// RUN: clang -emit-llvm < %s 2>&1 | grep 'addrspace(1)' | count 5
+// RUN: clang -emit-llvm < %s 2>&1 | grep 'addrspace(1)' | count 6
int foo __attribute__((address_space(1)));
int ban[10] __attribute__((address_space(1)));
result[i] = a; // expected-error {{assigning 'float4', expected 'int4'}}
}
+// PR2039
+typedef int a[5];
+void z() {
+ typedef const a b;
+ b r;
+ r[0]=10; // expected-error {{read-only variable is not assignable}}
+}
+
+int e(const a y) {
+ y[0] = 10; // expected-error {{read-only variable is not assignable}}
+}
+