Index: clang/include/clang/AST/ASTContext.h =================================================================== --- clang/include/clang/AST/ASTContext.h +++ clang/include/clang/AST/ASTContext.h @@ -2865,17 +2865,19 @@ void InitBuiltinType(CanQualType &R, BuiltinType::Kind K); // Return the Objective-C type encoding for a given type. - void getObjCEncodingForTypeImpl(QualType t, std::string &S, - bool ExpandPointedToStructures, - bool ExpandStructures, + enum { + OCET_ExpandPointedToStructures = 1 << 0, + OCET_ExpandStructures = 1 << 1, + OCET_IsOutermostType = 1 << 2, + OCET_EncodingProperty = 1 << 3, + OCET_IsStructField = 1 << 4, + OCET_EncodeBlockParameters = 1 << 5, + OCET_EncodeClassNames = 1 << 6, + OCET_EncodePointerToObjCTypedef = 1 << 7, + }; + void getObjCEncodingForTypeImpl(QualType t, std::string &S, unsigned Options, const FieldDecl *Field, - bool OutermostType = false, - bool EncodingProperty = false, - bool StructField = false, - bool EncodeBlockParameters = false, - bool EncodeClassNames = false, - bool EncodePointerToObjCTypedef = false, - QualType *NotEncodedT=nullptr) const; + QualType *NotEncodedT = nullptr) const; // Adds the encoding of the structure's members. void getObjCEncodingForStructureImpl(RecordDecl *RD, std::string &S, Index: clang/lib/AST/ASTContext.cpp =================================================================== --- clang/lib/AST/ASTContext.cpp +++ clang/lib/AST/ASTContext.cpp @@ -6303,13 +6303,11 @@ // Encode type qualifer, 'in', 'inout', etc. for the parameter. getObjCEncodingForTypeQualifier(QT, S); // Encode parameter type. - getObjCEncodingForTypeImpl(T, S, /*ExpandPointedToStructures=*/true, - /*ExpandStructures=*/true, /*Field=*/nullptr, - /*OutermostType=*/true, - /*EncodingProperty=*/false, - /*StructField=*/false, - /*EncodeBlockParameters=*/Extended, - /*EncodeClassNames=*/Extended); + unsigned Options = OCET_ExpandPointedToStructures | OCET_ExpandStructures | + OCET_IsOutermostType; + if (Extended) + Options |= OCET_EncodeBlockParameters | OCET_EncodeClassNames; + getObjCEncodingForTypeImpl(T, S, Options, /*Field=*/nullptr); } /// getObjCEncodingForMethodDecl - Return the encoded type for this method @@ -6501,13 +6499,10 @@ // directly pointed to, and expanding embedded structures. Note that // these rules are sufficient to prevent recursive encoding of the // same type. - getObjCEncodingForTypeImpl(T, S, /*ExpandPointedToStructures=*/true, - /*ExpandStructures=*/true, Field, - /*OutermostType=*/true, /*EncodingProperty=*/false, - /*StructField=*/false, - /*EncodeBlockParameters=*/false, - /*EncodeClassNames=*/false, - /*EncodePointerToObjCTypedef=*/false, NotEncodedT); + getObjCEncodingForTypeImpl(T, S, + OCET_ExpandPointedToStructures | + OCET_ExpandStructures | OCET_IsOutermostType, + Field, NotEncodedT); } void ASTContext::getObjCEncodingForPropertyType(QualType T, @@ -6515,9 +6510,11 @@ // Encode result type. // GCC has some special rules regarding encoding of properties which // closely resembles encoding of ivars. - getObjCEncodingForTypeImpl( - T, S, /*ExpandPointedToStructures=*/true, /*ExpandStructures=*/true, - /*Field=*/nullptr, /*OutermostType=*/true, /*EncodingProperty=*/true); + getObjCEncodingForTypeImpl(T, S, + OCET_ExpandPointedToStructures | + OCET_ExpandStructures | + OCET_IsOutermostType | OCET_EncodingProperty, + /*Field=*/nullptr); } static char getObjCEncodingForPrimitiveKind(const ASTContext *C, @@ -6664,16 +6661,9 @@ } // FIXME: Use SmallString for accumulating string. -void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, - bool ExpandPointedToStructures, - bool ExpandStructures, +void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string &S, + unsigned Options, const FieldDecl *FD, - bool OutermostType, - bool EncodingProperty, - bool StructField, - bool EncodeBlockParameters, - bool EncodeClassNames, - bool EncodePointerToObjCTypedef, QualType *NotEncodedT) const { CanQualType CT = getCanonicalType(T); switch (CT->getTypeClass()) { @@ -6690,18 +6680,14 @@ case Type::Complex: { const auto *CT = T->castAs(); S += 'j'; - getObjCEncodingForTypeImpl(CT->getElementType(), S, - /*ExpandPointedToStructures=*/false, - /*ExpandStructures=*/false, /*Field=*/nullptr); + getObjCEncodingForTypeImpl(CT->getElementType(), S, 0, /*Field=*/nullptr); return; } case Type::Atomic: { const auto *AT = T->castAs(); S += 'A'; - getObjCEncodingForTypeImpl(AT->getValueType(), S, - /*ExpandPointedToStructures=*/false, - /*ExpandStructures=*/false, /*Field=*/nullptr); + getObjCEncodingForTypeImpl(AT->getValueType(), S, 0, /*Field=*/nullptr); return; } @@ -6727,11 +6713,11 @@ // the pointer itself gets ignored, _unless_ we are looking at a typedef! // Also, do not emit the 'r' for anything but the outermost type! if (isa(T.getTypePtr())) { - if (OutermostType && T.isConstQualified()) { + if ((Options & OCET_IsOutermostType) && T.isConstQualified()) { isReadOnly = true; S += 'r'; } - } else if (OutermostType) { + } else if (Options & OCET_IsOutermostType) { QualType P = PointeeTy; while (P->getAs()) P = P->getAs()->getPointeeType(); @@ -6771,13 +6757,11 @@ S += '^'; getLegacyIntegralTypeEncoding(PointeeTy); - getObjCEncodingForTypeImpl( - PointeeTy, S, /*ExpandPointedToStructures=*/false, - /*ExpandStructures=*/ExpandPointedToStructures, /*Field=*/nullptr, - /*OutermostType=*/false, /*EncodingProperty=*/false, - /*StructField=*/false, /*EncodeBlockParameters=*/false, - /*EncodeClassNames=*/false, /*EncodePointerToObjCTypedef=*/false, - NotEncodedT); + getObjCEncodingForTypeImpl(PointeeTy, S, + (Options & OCET_ExpandPointedToStructures) + ? OCET_ExpandStructures + : 0, + /*Field=*/nullptr, NotEncodedT); return; } @@ -6786,13 +6770,12 @@ case Type::VariableArray: { const auto *AT = cast(CT); - if (isa(AT) && !StructField) { + if (isa(AT) && !(Options & OCET_IsStructField)) { // Incomplete arrays are encoded as a pointer to the array element. S += '^'; getObjCEncodingForTypeImpl(AT->getElementType(), S, - /*ExpandPointedToStructures=*/false, - ExpandStructures, FD); + Options & OCET_ExpandStructures, FD); } else { S += '['; @@ -6805,13 +6788,9 @@ S += '0'; } - getObjCEncodingForTypeImpl( - AT->getElementType(), S, - /*ExpandPointedToStructures=*/false, ExpandStructures, FD, - /*OutermostType=*/false, - /*EncodingProperty=*/false, /*StructField=*/false, - /*EncodeBlockParameters=*/false, /*EncodeClassNames=*/false, - /*EncodePointerToObjCTypedef=*/false, NotEncodedT); + getObjCEncodingForTypeImpl(AT->getElementType(), S, + Options & OCET_ExpandStructures, FD, + NotEncodedT); S += ']'; } return; @@ -6837,7 +6816,7 @@ } else { S += '?'; } - if (ExpandStructures) { + if (Options & OCET_ExpandStructures) { S += '='; if (!RDecl->isUnion()) { getObjCEncodingForStructureImpl(RDecl, S, FD, true, NotEncodedT); @@ -6852,18 +6831,13 @@ // Special case bit-fields. if (Field->isBitField()) { getObjCEncodingForTypeImpl(Field->getType(), S, - /*ExpandPointedToStructures=*/false, - /*ExpandStructures=*/true, Field); + OCET_ExpandStructures, Field); } else { QualType qt = Field->getType(); getLegacyIntegralTypeEncoding(qt); getObjCEncodingForTypeImpl( - qt, S, /*ExpandPointedToStructures=*/false, - /*ExpandStructures=*/true, FD, /*OutermostType=*/false, - /*EncodingProperty=*/false, - /*StructField=*/true, /*EncodeBlockParameters=*/false, - /*EncodeClassNames=*/false, - /*EncodePointerToObjCTypedef=*/false, NotEncodedT); + qt, S, OCET_ExpandStructures | OCET_IsStructField, FD, + NotEncodedT); } } } @@ -6875,26 +6849,26 @@ case Type::BlockPointer: { const auto *BT = T->castAs(); S += "@?"; // Unlike a pointer-to-function, which is "^?". - if (EncodeBlockParameters) { + if (Options & OCET_EncodeBlockParameters) { const auto *FT = BT->getPointeeType()->castAs(); S += '<'; // Block return type - getObjCEncodingForTypeImpl( - FT->getReturnType(), S, ExpandPointedToStructures, ExpandStructures, - FD, /*OutermostType=*/false, EncodingProperty, - /*StructField=*/false, EncodeBlockParameters, EncodeClassNames, - /*EncodePointerToObjCTypedef=*/false, NotEncodedT); + getObjCEncodingForTypeImpl(FT->getReturnType(), S, + Options & ~(OCET_IsOutermostType | + OCET_IsStructField | + OCET_EncodePointerToObjCTypedef), + FD, NotEncodedT); // Block self S += "@?"; // Block parameters if (const auto *FPT = dyn_cast(FT)) { for (const auto &I : FPT->param_types()) getObjCEncodingForTypeImpl( - I, S, ExpandPointedToStructures, ExpandStructures, FD, - /*OutermostType=*/false, EncodingProperty, - /*StructField=*/false, EncodeBlockParameters, EncodeClassNames, - /*EncodePointerToObjCTypedef=*/false, NotEncodedT); + I, S, + Options & ~(OCET_IsOutermostType | OCET_IsStructField | + OCET_EncodePointerToObjCTypedef), + FD, NotEncodedT); } S += '>'; } @@ -6922,7 +6896,7 @@ ObjCInterfaceDecl *OI = T->castAs()->getInterface(); S += '{'; S += OI->getObjCRuntimeNameAsString(); - if (ExpandStructures) { + if (Options & OCET_ExpandStructures) { S += '='; SmallVector Ivars; DeepCollectObjCIvars(OI, true, Ivars); @@ -6930,17 +6904,13 @@ const FieldDecl *Field = Ivars[i]; if (Field->isBitField()) getObjCEncodingForTypeImpl(Field->getType(), S, - /*ExpandPointedToStructures=*/false, - /*ExpandStructures=*/true, Field); + OCET_ExpandStructures, Field); else getObjCEncodingForTypeImpl( Field->getType(), S, - /*ExpandPointedToStructures=*/false, - /*ExpandStructures=*/true, FD, /*OutermostType=*/false, - /*EncodingProperty=*/false, - /*StructField=*/false, /*EncodeBlockParameters=*/false, - /*EncodeClassNames=*/false, EncodePointerToObjCTypedef, - NotEncodedT); + OCET_ExpandStructures | + (Options & OCET_EncodePointerToObjCTypedef), + FD, NotEncodedT); } } S += '}'; @@ -6963,10 +6933,11 @@ } if (OPT->isObjCQualifiedIdType()) { - getObjCEncodingForTypeImpl(getObjCIdType(), S, - ExpandPointedToStructures, - ExpandStructures, FD); - if (FD || EncodingProperty || EncodeClassNames) { + getObjCEncodingForTypeImpl( + getObjCIdType(), S, + Options & (OCET_ExpandPointedToStructures | OCET_ExpandStructures), + FD); + if (FD || (Options & (OCET_EncodingProperty | OCET_EncodeClassNames))) { // Note that we do extended encoding of protocol qualifer list // Only when doing ivar or property encoding. S += '"'; @@ -6981,9 +6952,9 @@ } QualType PointeeTy = OPT->getPointeeType(); - if (!EncodingProperty && - isa(PointeeTy.getTypePtr()) && - !EncodePointerToObjCTypedef) { + if (!(Options & + (OCET_EncodingProperty | OCET_EncodePointerToObjCTypedef)) && + isa(PointeeTy.getTypePtr())) { // Another historical/compatibility reason. // We encode the underlying type which comes out as // {...}; @@ -7004,19 +6975,17 @@ } getObjCEncodingForTypeImpl( PointeeTy, S, - /*ExpandPointedToStructures=*/false, - /*ExpandStructures=*/ExpandPointedToStructures, - /*Field=*/nullptr, - /*OutermostType=*/false, /*EncodingProperty=*/false, - /*StructField=*/false, /*EncodeBlockParameters=*/false, - /*EncodeClassNames=*/false, - /*EncodePointerToObjCTypedef=*/true); + OCET_EncodePointerToObjCTypedef | + ((Options & OCET_ExpandPointedToStructures) + ? OCET_ExpandStructures + : 0), + /*Field=*/nullptr); return; } S += '@'; if (OPT->getInterfaceDecl() && - (FD || EncodingProperty || EncodeClassNames)) { + (FD || (Options & (OCET_EncodingProperty | OCET_EncodeClassNames)))) { S += '"'; S += OPT->getInterfaceDecl()->getObjCRuntimeNameAsString(); for (const auto *I : OPT->quals()) { @@ -7192,14 +7161,9 @@ } else { QualType qt = field->getType(); getLegacyIntegralTypeEncoding(qt); - getObjCEncodingForTypeImpl( - qt, S, /*ExpandPointedToStructures=*/false, - /*ExpandStructures=*/true, FD, - /*OutermostType=*/false, - /*EncodingProperty=*/false, - /*StructField=*/true, /*EncodeBlockParameters=*/false, - /*EncodeClassNames=*/false, /*EncodePointerToObjCTypedef=*/false, - NotEncodedT); + getObjCEncodingForTypeImpl(qt, S, + OCET_ExpandStructures | OCET_IsStructField, + FD, NotEncodedT); #ifndef NDEBUG CurOffs += getTypeSize(field->getType()); #endif