mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-28 02:16:06 +00:00
Objective-C. Warn when @encode'ing provides an incomplete
type encoding because in certain cases, such as for vector types, because we still haven't designed encoding for them. rdar://9255564 llvm-svn: 216301
This commit is contained in:
parent
e82d89cc37
commit
4bf437ecd8
@ -1379,7 +1379,8 @@ public:
|
||||
///
|
||||
/// If \p Field is specified then record field names are also encoded.
|
||||
void getObjCEncodingForType(QualType T, std::string &S,
|
||||
const FieldDecl *Field=nullptr) const;
|
||||
const FieldDecl *Field=nullptr,
|
||||
QualType *NotEncodedT=nullptr) const;
|
||||
|
||||
/// \brief Emit the Objective-C property type encoding for the given
|
||||
/// type \p T into \p S.
|
||||
@ -2275,12 +2276,14 @@ private:
|
||||
bool StructField = false,
|
||||
bool EncodeBlockParameters = false,
|
||||
bool EncodeClassNames = false,
|
||||
bool EncodePointerToObjCTypedef = false) const;
|
||||
bool EncodePointerToObjCTypedef = false,
|
||||
QualType *NotEncodedT=nullptr) const;
|
||||
|
||||
// Adds the encoding of the structure's members.
|
||||
void getObjCEncodingForStructureImpl(RecordDecl *RD, std::string &S,
|
||||
const FieldDecl *Field,
|
||||
bool includeVBases = true) const;
|
||||
bool includeVBases = true,
|
||||
QualType *NotEncodedT=nullptr) const;
|
||||
public:
|
||||
// Adds the encoding of a method parameter or return type.
|
||||
void getObjCEncodingForMethodParameter(Decl::ObjCDeclQualifier QT,
|
||||
|
@ -2195,6 +2195,9 @@ def warn_type_attribute_wrong_type : Warning<
|
||||
"'%0' only applies to %select{function|pointer|"
|
||||
"Objective-C object or block pointer}1 types; type here is %2">,
|
||||
InGroup<IgnoredAttributes>;
|
||||
def warn_incomplete_encoded_type : Warning<
|
||||
"encoding of %0 type is incomplete because %1 component has unknown encoding">,
|
||||
InGroup<DiagGroup<"encode-type">>;
|
||||
def warn_attribute_requires_functions_or_static_globals : Warning<
|
||||
"%0 only applies to variables with static storage duration and functions">,
|
||||
InGroup<IgnoredAttributes>;
|
||||
|
@ -5097,13 +5097,15 @@ void ASTContext::getLegacyIntegralTypeEncoding (QualType &PointeeTy) const {
|
||||
}
|
||||
|
||||
void ASTContext::getObjCEncodingForType(QualType T, std::string& S,
|
||||
const FieldDecl *Field) const {
|
||||
const FieldDecl *Field,
|
||||
QualType *NotEncodedT) const {
|
||||
// We follow the behavior of gcc, expanding structures which are
|
||||
// directly pointed to, and expanding embedded structures. Note that
|
||||
// these rules are sufficient to prevent recursive encoding of the
|
||||
// same type.
|
||||
getObjCEncodingForTypeImpl(T, S, true, true, Field,
|
||||
true /* outermost type */);
|
||||
true /* outermost type */, false, false,
|
||||
false, false, false, NotEncodedT);
|
||||
}
|
||||
|
||||
void ASTContext::getObjCEncodingForPropertyType(QualType T,
|
||||
@ -5229,7 +5231,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
|
||||
bool StructField,
|
||||
bool EncodeBlockParameters,
|
||||
bool EncodeClassNames,
|
||||
bool EncodePointerToObjCTypedef) const {
|
||||
bool EncodePointerToObjCTypedef,
|
||||
QualType *NotEncodedT) const {
|
||||
CanQualType CT = getCanonicalType(T);
|
||||
switch (CT->getTypeClass()) {
|
||||
case Type::Builtin:
|
||||
@ -5245,16 +5248,14 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
|
||||
case Type::Complex: {
|
||||
const ComplexType *CT = T->castAs<ComplexType>();
|
||||
S += 'j';
|
||||
getObjCEncodingForTypeImpl(CT->getElementType(), S, false, false, nullptr,
|
||||
false, false);
|
||||
getObjCEncodingForTypeImpl(CT->getElementType(), S, false, false, nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
case Type::Atomic: {
|
||||
const AtomicType *AT = T->castAs<AtomicType>();
|
||||
S += 'A';
|
||||
getObjCEncodingForTypeImpl(AT->getValueType(), S, false, false, nullptr,
|
||||
false, false);
|
||||
getObjCEncodingForTypeImpl(AT->getValueType(), S, false, false, nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -5325,7 +5326,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
|
||||
getLegacyIntegralTypeEncoding(PointeeTy);
|
||||
|
||||
getObjCEncodingForTypeImpl(PointeeTy, S, false, ExpandPointedToStructures,
|
||||
nullptr);
|
||||
nullptr, false, false, false, false, false, false,
|
||||
NotEncodedT);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -5353,7 +5355,9 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
|
||||
}
|
||||
|
||||
getObjCEncodingForTypeImpl(AT->getElementType(), S,
|
||||
false, ExpandStructures, FD);
|
||||
false, ExpandStructures, FD,
|
||||
false, false, false, false, false, false,
|
||||
NotEncodedT);
|
||||
S += ']';
|
||||
}
|
||||
return;
|
||||
@ -5385,7 +5389,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
|
||||
if (ExpandStructures) {
|
||||
S += '=';
|
||||
if (!RDecl->isUnion()) {
|
||||
getObjCEncodingForStructureImpl(RDecl, S, FD);
|
||||
getObjCEncodingForStructureImpl(RDecl, S, FD, true, NotEncodedT);
|
||||
} else {
|
||||
for (const auto *Field : RDecl->fields()) {
|
||||
if (FD) {
|
||||
@ -5404,7 +5408,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
|
||||
getObjCEncodingForTypeImpl(qt, S, false, true,
|
||||
FD, /*OutermostType*/false,
|
||||
/*EncodingProperty*/false,
|
||||
/*StructField*/true);
|
||||
/*StructField*/true,
|
||||
false, false, false, NotEncodedT);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5424,7 +5429,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
|
||||
getObjCEncodingForTypeImpl(
|
||||
FT->getReturnType(), S, ExpandPointedToStructures, ExpandStructures,
|
||||
FD, false /* OutermostType */, EncodingProperty,
|
||||
false /* StructField */, EncodeBlockParameters, EncodeClassNames);
|
||||
false /* StructField */, EncodeBlockParameters, EncodeClassNames, false,
|
||||
NotEncodedT);
|
||||
// Block self
|
||||
S += "@?";
|
||||
// Block parameters
|
||||
@ -5433,7 +5439,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
|
||||
getObjCEncodingForTypeImpl(
|
||||
I, S, ExpandPointedToStructures, ExpandStructures, FD,
|
||||
false /* OutermostType */, EncodingProperty,
|
||||
false /* StructField */, EncodeBlockParameters, EncodeClassNames);
|
||||
false /* StructField */, EncodeBlockParameters, EncodeClassNames,
|
||||
false, NotEncodedT);
|
||||
}
|
||||
S += '>';
|
||||
}
|
||||
@ -5475,7 +5482,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
|
||||
else
|
||||
getObjCEncodingForTypeImpl(Field->getType(), S, false, true, FD,
|
||||
false, false, false, false, false,
|
||||
EncodePointerToObjCTypedef);
|
||||
EncodePointerToObjCTypedef,
|
||||
NotEncodedT);
|
||||
}
|
||||
S += '}';
|
||||
return;
|
||||
@ -5562,19 +5570,21 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
|
||||
// gcc just blithely ignores member pointers.
|
||||
// FIXME: we shoul do better than that. 'M' is available.
|
||||
case Type::MemberPointer:
|
||||
return;
|
||||
|
||||
// This matches gcc's encoding, even though technically it is insufficient.
|
||||
//FIXME. We should do a better job than gcc.
|
||||
case Type::Vector:
|
||||
case Type::ExtVector:
|
||||
// This matches gcc's encoding, even though technically it is
|
||||
// insufficient.
|
||||
// FIXME. We should do a better job than gcc.
|
||||
return;
|
||||
|
||||
// Until we have a coherent encoding of these three types, issue warning.
|
||||
{ if (NotEncodedT)
|
||||
*NotEncodedT = T;
|
||||
return;
|
||||
}
|
||||
|
||||
// We could see an undeduced auto type here during error recovery.
|
||||
// Just ignore it.
|
||||
case Type::Auto:
|
||||
// We could see an undeduced auto type here during error recovery.
|
||||
// Just ignore it.
|
||||
return;
|
||||
|
||||
|
||||
#define ABSTRACT_TYPE(KIND, BASE)
|
||||
#define TYPE(KIND, BASE)
|
||||
@ -5593,7 +5603,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
|
||||
void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl,
|
||||
std::string &S,
|
||||
const FieldDecl *FD,
|
||||
bool includeVBases) const {
|
||||
bool includeVBases,
|
||||
QualType *NotEncodedT) const {
|
||||
assert(RDecl && "Expected non-null RecordDecl");
|
||||
assert(!RDecl->isUnion() && "Should not be called for unions");
|
||||
if (!RDecl->getDefinition())
|
||||
@ -5697,7 +5708,8 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl,
|
||||
// in the initial structure. Note that this differs from gcc which
|
||||
// expands virtual bases each time one is encountered in the hierarchy,
|
||||
// making the encoding type bigger than it really is.
|
||||
getObjCEncodingForStructureImpl(base, S, FD, /*includeVBases*/false);
|
||||
getObjCEncodingForStructureImpl(base, S, FD, /*includeVBases*/false,
|
||||
NotEncodedT);
|
||||
assert(!base->isEmpty());
|
||||
#ifndef NDEBUG
|
||||
CurOffs += toBits(getASTRecordLayout(base).getNonVirtualSize());
|
||||
@ -5721,7 +5733,8 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl,
|
||||
getObjCEncodingForTypeImpl(qt, S, false, true, FD,
|
||||
/*OutermostType*/false,
|
||||
/*EncodingProperty*/false,
|
||||
/*StructField*/true);
|
||||
/*StructField*/true,
|
||||
false, false, false, NotEncodedT);
|
||||
#ifndef NDEBUG
|
||||
CurOffs += getTypeSize(field->getType());
|
||||
#endif
|
||||
|
@ -995,7 +995,11 @@ ExprResult Sema::BuildObjCEncodeExpression(SourceLocation AtLoc,
|
||||
return ExprError();
|
||||
|
||||
std::string Str;
|
||||
Context.getObjCEncodingForType(EncodedType, Str);
|
||||
QualType NotEncodedT;
|
||||
Context.getObjCEncodingForType(EncodedType, Str, nullptr, &NotEncodedT);
|
||||
if (!NotEncodedT.isNull())
|
||||
Diag(AtLoc, diag::warn_incomplete_encoded_type)
|
||||
<< EncodedType << NotEncodedT;
|
||||
|
||||
// The type of @encode is the same as the type of the corresponding string,
|
||||
// which is an array type.
|
||||
|
@ -24,3 +24,22 @@ int main()
|
||||
int i;
|
||||
typeof(@encode(typeof(i))) e = @encode(typeof(Intf)); // expected-warning {{initializer-string for char array is too long}}
|
||||
}
|
||||
|
||||
// rdar://9255564
|
||||
typedef short short8 __attribute__((ext_vector_type(8)));
|
||||
|
||||
struct foo {
|
||||
char a;
|
||||
int b;
|
||||
long c;
|
||||
short8 d;
|
||||
int array[4];
|
||||
short int bitfield1:5;
|
||||
unsigned short bitfield2:11;
|
||||
char *string;
|
||||
};
|
||||
|
||||
const char *RetEncode () {
|
||||
return @encode(struct foo); // expected-warning {{encoding of 'struct foo' type is incomplete because 'short8' (vector of 8 'short' values) component has unknown encoding}}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user