|
@@ -172,16 +172,6 @@ namespace {
|
|
/// processing is complete.
|
|
/// processing is complete.
|
|
SmallVector<ParsedAttr *, 2> ignoredTypeAttrs;
|
|
SmallVector<ParsedAttr *, 2> ignoredTypeAttrs;
|
|
|
|
|
|
- /// Attributes corresponding to AttributedTypeLocs that we have not yet
|
|
|
|
- /// populated.
|
|
|
|
- // FIXME: The two-phase mechanism by which we construct Types and fill
|
|
|
|
- // their TypeLocs makes it hard to correctly assign these. We keep the
|
|
|
|
- // attributes in creation order as an attempt to make them line up
|
|
|
|
- // properly.
|
|
|
|
- using TypeAttrPair = std::pair<const AttributedType*, const Attr*>;
|
|
|
|
- SmallVector<TypeAttrPair, 8> AttrsForTypes;
|
|
|
|
- bool AttrsForTypesSorted = true;
|
|
|
|
-
|
|
|
|
public:
|
|
public:
|
|
TypeProcessingState(Sema &sema, Declarator &declarator)
|
|
TypeProcessingState(Sema &sema, Declarator &declarator)
|
|
: sema(sema), declarator(declarator),
|
|
: sema(sema), declarator(declarator),
|
|
@@ -240,43 +230,6 @@ namespace {
|
|
diagnoseBadTypeAttribute(getSema(), *Attr, type);
|
|
diagnoseBadTypeAttribute(getSema(), *Attr, type);
|
|
}
|
|
}
|
|
|
|
|
|
- /// Get an attributed type for the given attribute, and remember the Attr
|
|
|
|
- /// object so that we can attach it to the AttributedTypeLoc.
|
|
|
|
- QualType getAttributedType(Attr *A, QualType ModifiedType,
|
|
|
|
- QualType EquivType) {
|
|
|
|
- QualType T =
|
|
|
|
- sema.Context.getAttributedType(A->getKind(), ModifiedType, EquivType);
|
|
|
|
- AttrsForTypes.push_back({cast<AttributedType>(T.getTypePtr()), A});
|
|
|
|
- AttrsForTypesSorted = false;
|
|
|
|
- return T;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /// Extract and remove the Attr* for a given attributed type.
|
|
|
|
- const Attr *takeAttrForAttributedType(const AttributedType *AT) {
|
|
|
|
- if (!AttrsForTypesSorted) {
|
|
|
|
- std::stable_sort(AttrsForTypes.begin(), AttrsForTypes.end(),
|
|
|
|
- [](const TypeAttrPair &A, const TypeAttrPair &B) {
|
|
|
|
- return A.first < B.first;
|
|
|
|
- });
|
|
|
|
- AttrsForTypesSorted = true;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // FIXME: This is quadratic if we have lots of reuses of the same
|
|
|
|
- // attributed type.
|
|
|
|
- for (auto It = std::partition_point(
|
|
|
|
- AttrsForTypes.begin(), AttrsForTypes.end(),
|
|
|
|
- [=](const TypeAttrPair &A) { return A.first < AT; });
|
|
|
|
- It != AttrsForTypes.end() && It->first == AT; ++It) {
|
|
|
|
- if (It->second) {
|
|
|
|
- const Attr *Result = It->second;
|
|
|
|
- It->second = nullptr;
|
|
|
|
- return Result;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- llvm_unreachable("no Attr* for AttributedType*");
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
~TypeProcessingState() {
|
|
~TypeProcessingState() {
|
|
if (trivial) return;
|
|
if (trivial) return;
|
|
|
|
|
|
@@ -3879,32 +3832,6 @@ static bool hasOuterPointerLikeChunk(const Declarator &D, unsigned endIndex) {
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
-template<typename AttrT>
|
|
|
|
-static AttrT *createSimpleAttr(ASTContext &Ctx, ParsedAttr &Attr) {
|
|
|
|
- Attr.setUsedAsTypeAttr();
|
|
|
|
- return ::new (Ctx)
|
|
|
|
- AttrT(Attr.getRange(), Ctx, Attr.getAttributeSpellingListIndex());
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static Attr *createNullabilityAttr(ASTContext &Ctx, ParsedAttr &Attr,
|
|
|
|
- NullabilityKind NK) {
|
|
|
|
- switch (NK) {
|
|
|
|
- case NullabilityKind::NonNull:
|
|
|
|
- return createSimpleAttr<TypeNonNullAttr>(Ctx, Attr);
|
|
|
|
-
|
|
|
|
- case NullabilityKind::Nullable:
|
|
|
|
- return createSimpleAttr<TypeNullableAttr>(Ctx, Attr);
|
|
|
|
-
|
|
|
|
- case NullabilityKind::Unspecified:
|
|
|
|
- return createSimpleAttr<TypeNullUnspecifiedAttr>(Ctx, Attr);
|
|
|
|
- }
|
|
|
|
- llvm_unreachable("unknown NullabilityKind");
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static TypeSourceInfo *
|
|
|
|
-GetTypeSourceInfoForDeclarator(TypeProcessingState &State,
|
|
|
|
- QualType T, TypeSourceInfo *ReturnTypeInfo);
|
|
|
|
-
|
|
|
|
static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
|
static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
|
QualType declSpecType,
|
|
QualType declSpecType,
|
|
TypeSourceInfo *TInfo) {
|
|
TypeSourceInfo *TInfo) {
|
|
@@ -4257,8 +4184,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
|
pointerKind, D.getDeclSpec().getTypeSpecTypeLoc(),
|
|
pointerKind, D.getDeclSpec().getTypeSpecTypeLoc(),
|
|
D.getDeclSpec().getEndLoc(),
|
|
D.getDeclSpec().getEndLoc(),
|
|
D.getMutableDeclSpec().getAttributes())) {
|
|
D.getMutableDeclSpec().getAttributes())) {
|
|
- T = state.getAttributedType(
|
|
|
|
- createNullabilityAttr(Context, *attr, *inferNullability), T, T);
|
|
|
|
|
|
+ T = Context.getAttributedType(
|
|
|
|
+ AttributedType::getNullabilityAttrKind(*inferNullability),T,T);
|
|
|
|
+ attr->setUsedAsTypeAttr();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -5097,7 +5025,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
|
if (D.isInvalidType())
|
|
if (D.isInvalidType())
|
|
return Context.getTrivialTypeSourceInfo(T);
|
|
return Context.getTrivialTypeSourceInfo(T);
|
|
|
|
|
|
- return GetTypeSourceInfoForDeclarator(state, T, TInfo);
|
|
|
|
|
|
+ return S.GetTypeSourceInfoForDeclarator(D, T, TInfo);
|
|
}
|
|
}
|
|
|
|
|
|
/// GetTypeForDeclarator - Convert the type for the specified
|
|
/// GetTypeForDeclarator - Convert the type for the specified
|
|
@@ -5233,25 +5161,131 @@ TypeSourceInfo *Sema::GetTypeForDeclaratorCast(Declarator &D, QualType FromTy) {
|
|
return GetFullTypeForDeclarator(state, declSpecTy, ReturnTypeInfo);
|
|
return GetFullTypeForDeclarator(state, declSpecTy, ReturnTypeInfo);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/// Map an AttributedType::Kind to an ParsedAttr::Kind.
|
|
|
|
+static ParsedAttr::Kind getAttrListKind(AttributedType::Kind kind) {
|
|
|
|
+ switch (kind) {
|
|
|
|
+ case AttributedType::attr_address_space:
|
|
|
|
+ return ParsedAttr::AT_AddressSpace;
|
|
|
|
+ case AttributedType::attr_regparm:
|
|
|
|
+ return ParsedAttr::AT_Regparm;
|
|
|
|
+ case AttributedType::attr_vector_size:
|
|
|
|
+ return ParsedAttr::AT_VectorSize;
|
|
|
|
+ case AttributedType::attr_neon_vector_type:
|
|
|
|
+ return ParsedAttr::AT_NeonVectorType;
|
|
|
|
+ case AttributedType::attr_neon_polyvector_type:
|
|
|
|
+ return ParsedAttr::AT_NeonPolyVectorType;
|
|
|
|
+ case AttributedType::attr_objc_gc:
|
|
|
|
+ return ParsedAttr::AT_ObjCGC;
|
|
|
|
+ case AttributedType::attr_objc_ownership:
|
|
|
|
+ case AttributedType::attr_objc_inert_unsafe_unretained:
|
|
|
|
+ return ParsedAttr::AT_ObjCOwnership;
|
|
|
|
+ case AttributedType::attr_noreturn:
|
|
|
|
+ return ParsedAttr::AT_NoReturn;
|
|
|
|
+ case AttributedType::attr_nocf_check:
|
|
|
|
+ return ParsedAttr::AT_AnyX86NoCfCheck;
|
|
|
|
+ case AttributedType::attr_cdecl:
|
|
|
|
+ return ParsedAttr::AT_CDecl;
|
|
|
|
+ case AttributedType::attr_fastcall:
|
|
|
|
+ return ParsedAttr::AT_FastCall;
|
|
|
|
+ case AttributedType::attr_stdcall:
|
|
|
|
+ return ParsedAttr::AT_StdCall;
|
|
|
|
+ case AttributedType::attr_thiscall:
|
|
|
|
+ return ParsedAttr::AT_ThisCall;
|
|
|
|
+ case AttributedType::attr_regcall:
|
|
|
|
+ return ParsedAttr::AT_RegCall;
|
|
|
|
+ case AttributedType::attr_pascal:
|
|
|
|
+ return ParsedAttr::AT_Pascal;
|
|
|
|
+ case AttributedType::attr_swiftcall:
|
|
|
|
+ return ParsedAttr::AT_SwiftCall;
|
|
|
|
+ case AttributedType::attr_vectorcall:
|
|
|
|
+ return ParsedAttr::AT_VectorCall;
|
|
|
|
+ case AttributedType::attr_pcs:
|
|
|
|
+ case AttributedType::attr_pcs_vfp:
|
|
|
|
+ return ParsedAttr::AT_Pcs;
|
|
|
|
+ case AttributedType::attr_inteloclbicc:
|
|
|
|
+ return ParsedAttr::AT_IntelOclBicc;
|
|
|
|
+ case AttributedType::attr_ms_abi:
|
|
|
|
+ return ParsedAttr::AT_MSABI;
|
|
|
|
+ case AttributedType::attr_sysv_abi:
|
|
|
|
+ return ParsedAttr::AT_SysVABI;
|
|
|
|
+ case AttributedType::attr_preserve_most:
|
|
|
|
+ return ParsedAttr::AT_PreserveMost;
|
|
|
|
+ case AttributedType::attr_preserve_all:
|
|
|
|
+ return ParsedAttr::AT_PreserveAll;
|
|
|
|
+ case AttributedType::attr_ptr32:
|
|
|
|
+ return ParsedAttr::AT_Ptr32;
|
|
|
|
+ case AttributedType::attr_ptr64:
|
|
|
|
+ return ParsedAttr::AT_Ptr64;
|
|
|
|
+ case AttributedType::attr_sptr:
|
|
|
|
+ return ParsedAttr::AT_SPtr;
|
|
|
|
+ case AttributedType::attr_uptr:
|
|
|
|
+ return ParsedAttr::AT_UPtr;
|
|
|
|
+ case AttributedType::attr_nonnull:
|
|
|
|
+ return ParsedAttr::AT_TypeNonNull;
|
|
|
|
+ case AttributedType::attr_nullable:
|
|
|
|
+ return ParsedAttr::AT_TypeNullable;
|
|
|
|
+ case AttributedType::attr_null_unspecified:
|
|
|
|
+ return ParsedAttr::AT_TypeNullUnspecified;
|
|
|
|
+ case AttributedType::attr_objc_kindof:
|
|
|
|
+ return ParsedAttr::AT_ObjCKindOf;
|
|
|
|
+ case AttributedType::attr_ns_returns_retained:
|
|
|
|
+ return ParsedAttr::AT_NSReturnsRetained;
|
|
|
|
+ case AttributedType::attr_lifetimebound:
|
|
|
|
+ return ParsedAttr::AT_LifetimeBound;
|
|
|
|
+ }
|
|
|
|
+ llvm_unreachable("unexpected attribute kind!");
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void setAttributedTypeLoc(AttributedTypeLoc TL, const ParsedAttr &attr) {
|
|
|
|
+ TL.setAttrNameLoc(attr.getLoc());
|
|
|
|
+ if (TL.hasAttrExprOperand()) {
|
|
|
|
+ assert(attr.isArgExpr(0) && "mismatched attribute operand kind");
|
|
|
|
+ TL.setAttrExprOperand(attr.getArgAsExpr(0));
|
|
|
|
+ } else if (TL.hasAttrEnumOperand()) {
|
|
|
|
+ assert((attr.isArgIdent(0) || attr.isArgExpr(0)) &&
|
|
|
|
+ "unexpected attribute operand kind");
|
|
|
|
+ if (attr.isArgIdent(0))
|
|
|
|
+ TL.setAttrEnumOperandLoc(attr.getArgAsIdent(0)->Loc);
|
|
|
|
+ else
|
|
|
|
+ TL.setAttrEnumOperandLoc(attr.getArgAsExpr(0)->getExprLoc());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // FIXME: preserve this information to here.
|
|
|
|
+ if (TL.hasAttrOperand())
|
|
|
|
+ TL.setAttrOperandParensRange(SourceRange());
|
|
|
|
+}
|
|
|
|
+
|
|
static void fillAttributedTypeLoc(AttributedTypeLoc TL,
|
|
static void fillAttributedTypeLoc(AttributedTypeLoc TL,
|
|
- TypeProcessingState &State) {
|
|
|
|
- TL.setAttr(State.takeAttrForAttributedType(TL.getTypePtr()));
|
|
|
|
|
|
+ const ParsedAttributesView &Attrs,
|
|
|
|
+ const ParsedAttributesView &DeclAttrs) {
|
|
|
|
+ // DeclAttrs and Attrs cannot be both empty.
|
|
|
|
+ assert((!Attrs.empty() || !DeclAttrs.empty()) &&
|
|
|
|
+ "no type attributes in the expected location!");
|
|
|
|
+
|
|
|
|
+ ParsedAttr::Kind parsedKind = getAttrListKind(TL.getAttrKind());
|
|
|
|
+ // Try to search for an attribute of matching kind in Attrs list.
|
|
|
|
+ for (const ParsedAttr &AL : Attrs)
|
|
|
|
+ if (AL.getKind() == parsedKind)
|
|
|
|
+ return setAttributedTypeLoc(TL, AL);
|
|
|
|
+
|
|
|
|
+ for (const ParsedAttr &AL : DeclAttrs)
|
|
|
|
+ if (AL.isCXX11Attribute() || AL.getKind() == parsedKind)
|
|
|
|
+ return setAttributedTypeLoc(TL, AL);
|
|
|
|
+ llvm_unreachable("no matching type attribute in expected location!");
|
|
}
|
|
}
|
|
|
|
|
|
namespace {
|
|
namespace {
|
|
class TypeSpecLocFiller : public TypeLocVisitor<TypeSpecLocFiller> {
|
|
class TypeSpecLocFiller : public TypeLocVisitor<TypeSpecLocFiller> {
|
|
ASTContext &Context;
|
|
ASTContext &Context;
|
|
- TypeProcessingState &State;
|
|
|
|
const DeclSpec &DS;
|
|
const DeclSpec &DS;
|
|
|
|
|
|
public:
|
|
public:
|
|
- TypeSpecLocFiller(ASTContext &Context, TypeProcessingState &State,
|
|
|
|
- const DeclSpec &DS)
|
|
|
|
- : Context(Context), State(State), DS(DS) {}
|
|
|
|
|
|
+ TypeSpecLocFiller(ASTContext &Context, const DeclSpec &DS)
|
|
|
|
+ : Context(Context), DS(DS) {}
|
|
|
|
|
|
void VisitAttributedTypeLoc(AttributedTypeLoc TL) {
|
|
void VisitAttributedTypeLoc(AttributedTypeLoc TL) {
|
|
|
|
+ fillAttributedTypeLoc(TL, DS.getAttributes(), ParsedAttributesView{});
|
|
Visit(TL.getModifiedLoc());
|
|
Visit(TL.getModifiedLoc());
|
|
- fillAttributedTypeLoc(TL, State);
|
|
|
|
}
|
|
}
|
|
void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
|
|
void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
|
|
Visit(TL.getUnqualifiedLoc());
|
|
Visit(TL.getUnqualifiedLoc());
|
|
@@ -5408,13 +5442,11 @@ namespace {
|
|
|
|
|
|
class DeclaratorLocFiller : public TypeLocVisitor<DeclaratorLocFiller> {
|
|
class DeclaratorLocFiller : public TypeLocVisitor<DeclaratorLocFiller> {
|
|
ASTContext &Context;
|
|
ASTContext &Context;
|
|
- TypeProcessingState &State;
|
|
|
|
const DeclaratorChunk &Chunk;
|
|
const DeclaratorChunk &Chunk;
|
|
|
|
|
|
public:
|
|
public:
|
|
- DeclaratorLocFiller(ASTContext &Context, TypeProcessingState &State,
|
|
|
|
- const DeclaratorChunk &Chunk)
|
|
|
|
- : Context(Context), State(State), Chunk(Chunk) {}
|
|
|
|
|
|
+ DeclaratorLocFiller(ASTContext &Context, const DeclaratorChunk &Chunk)
|
|
|
|
+ : Context(Context), Chunk(Chunk) {}
|
|
|
|
|
|
void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
|
|
void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
|
|
llvm_unreachable("qualified type locs not expected here!");
|
|
llvm_unreachable("qualified type locs not expected here!");
|
|
@@ -5424,7 +5456,7 @@ namespace {
|
|
}
|
|
}
|
|
|
|
|
|
void VisitAttributedTypeLoc(AttributedTypeLoc TL) {
|
|
void VisitAttributedTypeLoc(AttributedTypeLoc TL) {
|
|
- fillAttributedTypeLoc(TL, State);
|
|
|
|
|
|
+ fillAttributedTypeLoc(TL, Chunk.getAttrs(), ParsedAttributesView{});
|
|
}
|
|
}
|
|
void VisitAdjustedTypeLoc(AdjustedTypeLoc TL) {
|
|
void VisitAdjustedTypeLoc(AdjustedTypeLoc TL) {
|
|
// nothing
|
|
// nothing
|
|
@@ -5581,13 +5613,10 @@ fillDependentAddressSpaceTypeLoc(DependentAddressSpaceTypeLoc DASTL,
|
|
/// up in the normal place in the declaration specifiers (such as a C++
|
|
/// up in the normal place in the declaration specifiers (such as a C++
|
|
/// conversion function), this pointer will refer to a type source information
|
|
/// conversion function), this pointer will refer to a type source information
|
|
/// for that return type.
|
|
/// for that return type.
|
|
-static TypeSourceInfo *
|
|
|
|
-GetTypeSourceInfoForDeclarator(TypeProcessingState &State,
|
|
|
|
- QualType T, TypeSourceInfo *ReturnTypeInfo) {
|
|
|
|
- Sema &S = State.getSema();
|
|
|
|
- Declarator &D = State.getDeclarator();
|
|
|
|
-
|
|
|
|
- TypeSourceInfo *TInfo = S.Context.CreateTypeSourceInfo(T);
|
|
|
|
|
|
+TypeSourceInfo *
|
|
|
|
+Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
|
|
|
|
+ TypeSourceInfo *ReturnTypeInfo) {
|
|
|
|
+ TypeSourceInfo *TInfo = Context.CreateTypeSourceInfo(T);
|
|
UnqualTypeLoc CurrTL = TInfo->getTypeLoc().getUnqualifiedLoc();
|
|
UnqualTypeLoc CurrTL = TInfo->getTypeLoc().getUnqualifiedLoc();
|
|
|
|
|
|
// Handle parameter packs whose type is a pack expansion.
|
|
// Handle parameter packs whose type is a pack expansion.
|
|
@@ -5597,6 +5626,7 @@ GetTypeSourceInfoForDeclarator(TypeProcessingState &State,
|
|
}
|
|
}
|
|
|
|
|
|
for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
|
|
for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
|
|
|
|
+
|
|
if (DependentAddressSpaceTypeLoc DASTL =
|
|
if (DependentAddressSpaceTypeLoc DASTL =
|
|
CurrTL.getAs<DependentAddressSpaceTypeLoc>()) {
|
|
CurrTL.getAs<DependentAddressSpaceTypeLoc>()) {
|
|
fillDependentAddressSpaceTypeLoc(DASTL, D.getTypeObject(i).getAttrs());
|
|
fillDependentAddressSpaceTypeLoc(DASTL, D.getTypeObject(i).getAttrs());
|
|
@@ -5611,7 +5641,8 @@ GetTypeSourceInfoForDeclarator(TypeProcessingState &State,
|
|
}
|
|
}
|
|
|
|
|
|
while (AttributedTypeLoc TL = CurrTL.getAs<AttributedTypeLoc>()) {
|
|
while (AttributedTypeLoc TL = CurrTL.getAs<AttributedTypeLoc>()) {
|
|
- fillAttributedTypeLoc(TL, State);
|
|
|
|
|
|
+ fillAttributedTypeLoc(TL, D.getTypeObject(i).getAttrs(),
|
|
|
|
+ D.getAttributes());
|
|
CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
|
|
CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
|
|
}
|
|
}
|
|
|
|
|
|
@@ -5619,7 +5650,7 @@ GetTypeSourceInfoForDeclarator(TypeProcessingState &State,
|
|
while (AdjustedTypeLoc TL = CurrTL.getAs<AdjustedTypeLoc>())
|
|
while (AdjustedTypeLoc TL = CurrTL.getAs<AdjustedTypeLoc>())
|
|
CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
|
|
CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
|
|
|
|
|
|
- DeclaratorLocFiller(S.Context, State, D.getTypeObject(i)).Visit(CurrTL);
|
|
|
|
|
|
+ DeclaratorLocFiller(Context, D.getTypeObject(i)).Visit(CurrTL);
|
|
CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc();
|
|
CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc();
|
|
}
|
|
}
|
|
|
|
|
|
@@ -5630,7 +5661,7 @@ GetTypeSourceInfoForDeclarator(TypeProcessingState &State,
|
|
assert(TL.getFullDataSize() == CurrTL.getFullDataSize());
|
|
assert(TL.getFullDataSize() == CurrTL.getFullDataSize());
|
|
memcpy(CurrTL.getOpaqueData(), TL.getOpaqueData(), TL.getFullDataSize());
|
|
memcpy(CurrTL.getOpaqueData(), TL.getOpaqueData(), TL.getFullDataSize());
|
|
} else {
|
|
} else {
|
|
- TypeSpecLocFiller(S.Context, State, D.getDeclSpec()).Visit(CurrTL);
|
|
|
|
|
|
+ TypeSpecLocFiller(Context, D.getDeclSpec()).Visit(CurrTL);
|
|
}
|
|
}
|
|
|
|
|
|
return TInfo;
|
|
return TInfo;
|
|
@@ -5859,7 +5890,7 @@ static bool hasDirectOwnershipQualifier(QualType type) {
|
|
while (true) {
|
|
while (true) {
|
|
// __strong id
|
|
// __strong id
|
|
if (const AttributedType *attr = dyn_cast<AttributedType>(type)) {
|
|
if (const AttributedType *attr = dyn_cast<AttributedType>(type)) {
|
|
- if (attr->getAttrKind() == attr::ObjCOwnership)
|
|
|
|
|
|
+ if (attr->getAttrKind() == AttributedType::attr_objc_ownership)
|
|
return true;
|
|
return true;
|
|
|
|
|
|
type = attr->getModifiedType();
|
|
type = attr->getModifiedType();
|
|
@@ -6003,9 +6034,9 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
|
|
// the coexistence problems with __unsafe_unretained.
|
|
// the coexistence problems with __unsafe_unretained.
|
|
if (!S.getLangOpts().ObjCAutoRefCount &&
|
|
if (!S.getLangOpts().ObjCAutoRefCount &&
|
|
lifetime == Qualifiers::OCL_ExplicitNone) {
|
|
lifetime == Qualifiers::OCL_ExplicitNone) {
|
|
- type = state.getAttributedType(
|
|
|
|
- createSimpleAttr<ObjCInertUnsafeUnretainedAttr>(S.Context, attr),
|
|
|
|
- type, type);
|
|
|
|
|
|
+ type = S.Context.getAttributedType(
|
|
|
|
+ AttributedType::attr_objc_inert_unsafe_unretained,
|
|
|
|
+ type, type);
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -6015,12 +6046,9 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
|
|
|
|
|
|
// If we have a valid source location for the attribute, use an
|
|
// If we have a valid source location for the attribute, use an
|
|
// AttributedType instead.
|
|
// AttributedType instead.
|
|
- if (AttrLoc.isValid()) {
|
|
|
|
- type = state.getAttributedType(::new (S.Context) ObjCOwnershipAttr(
|
|
|
|
- attr.getRange(), S.Context, II,
|
|
|
|
- attr.getAttributeSpellingListIndex()),
|
|
|
|
- origType, type);
|
|
|
|
- }
|
|
|
|
|
|
+ if (AttrLoc.isValid())
|
|
|
|
+ type = S.Context.getAttributedType(AttributedType::attr_objc_ownership,
|
|
|
|
+ origType, type);
|
|
|
|
|
|
auto diagnoseOrDelay = [](Sema &S, SourceLocation loc,
|
|
auto diagnoseOrDelay = [](Sema &S, SourceLocation loc,
|
|
unsigned diagnostic, QualType type) {
|
|
unsigned diagnostic, QualType type) {
|
|
@@ -6120,10 +6148,8 @@ static bool handleObjCGCTypeAttr(TypeProcessingState &state, ParsedAttr &attr,
|
|
|
|
|
|
// Make an attributed type to preserve the source information.
|
|
// Make an attributed type to preserve the source information.
|
|
if (attr.getLoc().isValid())
|
|
if (attr.getLoc().isValid())
|
|
- type = state.getAttributedType(
|
|
|
|
- ::new (S.Context) ObjCGCAttr(attr.getRange(), S.Context, II,
|
|
|
|
- attr.getAttributeSpellingListIndex()),
|
|
|
|
- origType, type);
|
|
|
|
|
|
+ type = S.Context.getAttributedType(AttributedType::attr_objc_gc,
|
|
|
|
+ origType, type);
|
|
|
|
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
@@ -6266,50 +6292,37 @@ namespace {
|
|
} // end anonymous namespace
|
|
} // end anonymous namespace
|
|
|
|
|
|
static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State,
|
|
static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State,
|
|
- ParsedAttr &PAttr, QualType &Type) {
|
|
|
|
|
|
+ ParsedAttr &Attr, QualType &Type) {
|
|
Sema &S = State.getSema();
|
|
Sema &S = State.getSema();
|
|
|
|
|
|
- Attr *A;
|
|
|
|
- switch (PAttr.getKind()) {
|
|
|
|
- default: llvm_unreachable("Unknown attribute kind");
|
|
|
|
- case ParsedAttr::AT_Ptr32:
|
|
|
|
- A = createSimpleAttr<Ptr32Attr>(S.Context, PAttr);
|
|
|
|
- break;
|
|
|
|
- case ParsedAttr::AT_Ptr64:
|
|
|
|
- A = createSimpleAttr<Ptr64Attr>(S.Context, PAttr);
|
|
|
|
- break;
|
|
|
|
- case ParsedAttr::AT_SPtr:
|
|
|
|
- A = createSimpleAttr<SPtrAttr>(S.Context, PAttr);
|
|
|
|
- break;
|
|
|
|
- case ParsedAttr::AT_UPtr:
|
|
|
|
- A = createSimpleAttr<UPtrAttr>(S.Context, PAttr);
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- attr::Kind NewAttrKind = A->getKind();
|
|
|
|
|
|
+ ParsedAttr::Kind Kind = Attr.getKind();
|
|
QualType Desugared = Type;
|
|
QualType Desugared = Type;
|
|
const AttributedType *AT = dyn_cast<AttributedType>(Type);
|
|
const AttributedType *AT = dyn_cast<AttributedType>(Type);
|
|
while (AT) {
|
|
while (AT) {
|
|
- attr::Kind CurAttrKind = AT->getAttrKind();
|
|
|
|
|
|
+ AttributedType::Kind CurAttrKind = AT->getAttrKind();
|
|
|
|
|
|
// You cannot specify duplicate type attributes, so if the attribute has
|
|
// You cannot specify duplicate type attributes, so if the attribute has
|
|
// already been applied, flag it.
|
|
// already been applied, flag it.
|
|
- if (NewAttrKind == CurAttrKind) {
|
|
|
|
- S.Diag(PAttr.getLoc(), diag::warn_duplicate_attribute_exact)
|
|
|
|
- << PAttr.getName();
|
|
|
|
|
|
+ if (getAttrListKind(CurAttrKind) == Kind) {
|
|
|
|
+ S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute_exact)
|
|
|
|
+ << Attr.getName();
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
// You cannot have both __sptr and __uptr on the same type, nor can you
|
|
// You cannot have both __sptr and __uptr on the same type, nor can you
|
|
// have __ptr32 and __ptr64.
|
|
// have __ptr32 and __ptr64.
|
|
- if ((CurAttrKind == attr::Ptr32 && NewAttrKind == attr::Ptr64) ||
|
|
|
|
- (CurAttrKind == attr::Ptr64 && NewAttrKind == attr::Ptr32)) {
|
|
|
|
- S.Diag(PAttr.getLoc(), diag::err_attributes_are_not_compatible)
|
|
|
|
|
|
+ if ((CurAttrKind == AttributedType::attr_ptr32 &&
|
|
|
|
+ Kind == ParsedAttr::AT_Ptr64) ||
|
|
|
|
+ (CurAttrKind == AttributedType::attr_ptr64 &&
|
|
|
|
+ Kind == ParsedAttr::AT_Ptr32)) {
|
|
|
|
+ S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
|
|
<< "'__ptr32'" << "'__ptr64'";
|
|
<< "'__ptr32'" << "'__ptr64'";
|
|
return true;
|
|
return true;
|
|
- } else if ((CurAttrKind == attr::SPtr && NewAttrKind == attr::UPtr) ||
|
|
|
|
- (CurAttrKind == attr::UPtr && NewAttrKind == attr::SPtr)) {
|
|
|
|
- S.Diag(PAttr.getLoc(), diag::err_attributes_are_not_compatible)
|
|
|
|
|
|
+ } else if ((CurAttrKind == AttributedType::attr_sptr &&
|
|
|
|
+ Kind == ParsedAttr::AT_UPtr) ||
|
|
|
|
+ (CurAttrKind == AttributedType::attr_uptr &&
|
|
|
|
+ Kind == ParsedAttr::AT_SPtr)) {
|
|
|
|
+ S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
|
|
<< "'__sptr'" << "'__uptr'";
|
|
<< "'__sptr'" << "'__uptr'";
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
@@ -6320,64 +6333,41 @@ static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State,
|
|
|
|
|
|
// Pointer type qualifiers can only operate on pointer types, but not
|
|
// Pointer type qualifiers can only operate on pointer types, but not
|
|
// pointer-to-member types.
|
|
// pointer-to-member types.
|
|
- //
|
|
|
|
- // FIXME: Should we really be disallowing this attribute if there is any
|
|
|
|
- // type sugar between it and the pointer (other than attributes)? Eg, this
|
|
|
|
- // disallows the attribute on a parenthesized pointer.
|
|
|
|
- // And if so, should we really allow *any* type attribute?
|
|
|
|
if (!isa<PointerType>(Desugared)) {
|
|
if (!isa<PointerType>(Desugared)) {
|
|
if (Type->isMemberPointerType())
|
|
if (Type->isMemberPointerType())
|
|
- S.Diag(PAttr.getLoc(), diag::err_attribute_no_member_pointers) << PAttr;
|
|
|
|
|
|
+ S.Diag(Attr.getLoc(), diag::err_attribute_no_member_pointers) << Attr;
|
|
else
|
|
else
|
|
- S.Diag(PAttr.getLoc(), diag::err_attribute_pointers_only) << PAttr << 0;
|
|
|
|
|
|
+ S.Diag(Attr.getLoc(), diag::err_attribute_pointers_only) << Attr << 0;
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
- Type = State.getAttributedType(A, Type, Type);
|
|
|
|
- return false;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-/// Map a nullability attribute kind to a nullability kind.
|
|
|
|
-static NullabilityKind mapNullabilityAttrKind(ParsedAttr::Kind kind) {
|
|
|
|
- switch (kind) {
|
|
|
|
- case ParsedAttr::AT_TypeNonNull:
|
|
|
|
- return NullabilityKind::NonNull;
|
|
|
|
-
|
|
|
|
- case ParsedAttr::AT_TypeNullable:
|
|
|
|
- return NullabilityKind::Nullable;
|
|
|
|
-
|
|
|
|
- case ParsedAttr::AT_TypeNullUnspecified:
|
|
|
|
- return NullabilityKind::Unspecified;
|
|
|
|
-
|
|
|
|
- default:
|
|
|
|
- llvm_unreachable("not a nullability attribute kind");
|
|
|
|
|
|
+ AttributedType::Kind TAK;
|
|
|
|
+ switch (Kind) {
|
|
|
|
+ default: llvm_unreachable("Unknown attribute kind");
|
|
|
|
+ case ParsedAttr::AT_Ptr32:
|
|
|
|
+ TAK = AttributedType::attr_ptr32;
|
|
|
|
+ break;
|
|
|
|
+ case ParsedAttr::AT_Ptr64:
|
|
|
|
+ TAK = AttributedType::attr_ptr64;
|
|
|
|
+ break;
|
|
|
|
+ case ParsedAttr::AT_SPtr:
|
|
|
|
+ TAK = AttributedType::attr_sptr;
|
|
|
|
+ break;
|
|
|
|
+ case ParsedAttr::AT_UPtr:
|
|
|
|
+ TAK = AttributedType::attr_uptr;
|
|
|
|
+ break;
|
|
}
|
|
}
|
|
-}
|
|
|
|
|
|
|
|
-/// Applies a nullability type specifier to the given type, if possible.
|
|
|
|
-///
|
|
|
|
-/// \param state The type processing state.
|
|
|
|
-///
|
|
|
|
-/// \param type The type to which the nullability specifier will be
|
|
|
|
-/// added. On success, this type will be updated appropriately.
|
|
|
|
-///
|
|
|
|
-/// \param attr The attribute as written on the type.
|
|
|
|
-///
|
|
|
|
-/// \param allowArrayTypes Whether to accept nullability specifiers on an
|
|
|
|
-/// array type (e.g., because it will decay to a pointer).
|
|
|
|
-///
|
|
|
|
-/// \returns true if a problem has been diagnosed, false on success.
|
|
|
|
-static bool checkNullabilityTypeSpecifier(TypeProcessingState &state,
|
|
|
|
- QualType &type,
|
|
|
|
- ParsedAttr &attr,
|
|
|
|
- bool allowOnArrayType) {
|
|
|
|
- Sema &S = state.getSema();
|
|
|
|
-
|
|
|
|
- NullabilityKind nullability = mapNullabilityAttrKind(attr.getKind());
|
|
|
|
- SourceLocation nullabilityLoc = attr.getLoc();
|
|
|
|
- bool isContextSensitive = attr.isContextSensitiveKeywordAttribute();
|
|
|
|
|
|
+ Type = S.Context.getAttributedType(TAK, Type, Type);
|
|
|
|
+ return false;
|
|
|
|
+}
|
|
|
|
|
|
- recordNullabilitySeen(S, nullabilityLoc);
|
|
|
|
|
|
+bool Sema::checkNullabilityTypeSpecifier(QualType &type,
|
|
|
|
+ NullabilityKind nullability,
|
|
|
|
+ SourceLocation nullabilityLoc,
|
|
|
|
+ bool isContextSensitive,
|
|
|
|
+ bool allowOnArrayType) {
|
|
|
|
+ recordNullabilitySeen(*this, nullabilityLoc);
|
|
|
|
|
|
// Check for existing nullability attributes on the type.
|
|
// Check for existing nullability attributes on the type.
|
|
QualType desugared = type;
|
|
QualType desugared = type;
|
|
@@ -6386,7 +6376,7 @@ static bool checkNullabilityTypeSpecifier(TypeProcessingState &state,
|
|
if (auto existingNullability = attributed->getImmediateNullability()) {
|
|
if (auto existingNullability = attributed->getImmediateNullability()) {
|
|
// Duplicated nullability.
|
|
// Duplicated nullability.
|
|
if (nullability == *existingNullability) {
|
|
if (nullability == *existingNullability) {
|
|
- S.Diag(nullabilityLoc, diag::warn_nullability_duplicate)
|
|
|
|
|
|
+ Diag(nullabilityLoc, diag::warn_nullability_duplicate)
|
|
<< DiagNullabilityKind(nullability, isContextSensitive)
|
|
<< DiagNullabilityKind(nullability, isContextSensitive)
|
|
<< FixItHint::CreateRemoval(nullabilityLoc);
|
|
<< FixItHint::CreateRemoval(nullabilityLoc);
|
|
|
|
|
|
@@ -6394,7 +6384,7 @@ static bool checkNullabilityTypeSpecifier(TypeProcessingState &state,
|
|
}
|
|
}
|
|
|
|
|
|
// Conflicting nullability.
|
|
// Conflicting nullability.
|
|
- S.Diag(nullabilityLoc, diag::err_nullability_conflicting)
|
|
|
|
|
|
+ Diag(nullabilityLoc, diag::err_nullability_conflicting)
|
|
<< DiagNullabilityKind(nullability, isContextSensitive)
|
|
<< DiagNullabilityKind(nullability, isContextSensitive)
|
|
<< DiagNullabilityKind(*existingNullability, false);
|
|
<< DiagNullabilityKind(*existingNullability, false);
|
|
return true;
|
|
return true;
|
|
@@ -6407,9 +6397,9 @@ static bool checkNullabilityTypeSpecifier(TypeProcessingState &state,
|
|
// This (unlike the code above) looks through typedefs that might
|
|
// This (unlike the code above) looks through typedefs that might
|
|
// have nullability specifiers on them, which means we cannot
|
|
// have nullability specifiers on them, which means we cannot
|
|
// provide a useful Fix-It.
|
|
// provide a useful Fix-It.
|
|
- if (auto existingNullability = desugared->getNullability(S.Context)) {
|
|
|
|
|
|
+ if (auto existingNullability = desugared->getNullability(Context)) {
|
|
if (nullability != *existingNullability) {
|
|
if (nullability != *existingNullability) {
|
|
- S.Diag(nullabilityLoc, diag::err_nullability_conflicting)
|
|
|
|
|
|
+ Diag(nullabilityLoc, diag::err_nullability_conflicting)
|
|
<< DiagNullabilityKind(nullability, isContextSensitive)
|
|
<< DiagNullabilityKind(nullability, isContextSensitive)
|
|
<< DiagNullabilityKind(*existingNullability, false);
|
|
<< DiagNullabilityKind(*existingNullability, false);
|
|
|
|
|
|
@@ -6420,7 +6410,7 @@ static bool checkNullabilityTypeSpecifier(TypeProcessingState &state,
|
|
if (auto typedefNullability
|
|
if (auto typedefNullability
|
|
= AttributedType::stripOuterNullability(underlyingType)) {
|
|
= AttributedType::stripOuterNullability(underlyingType)) {
|
|
if (*typedefNullability == *existingNullability) {
|
|
if (*typedefNullability == *existingNullability) {
|
|
- S.Diag(typedefDecl->getLocation(), diag::note_nullability_here)
|
|
|
|
|
|
+ Diag(typedefDecl->getLocation(), diag::note_nullability_here)
|
|
<< DiagNullabilityKind(*existingNullability, false);
|
|
<< DiagNullabilityKind(*existingNullability, false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -6433,7 +6423,7 @@ static bool checkNullabilityTypeSpecifier(TypeProcessingState &state,
|
|
// If this definitely isn't a pointer type, reject the specifier.
|
|
// If this definitely isn't a pointer type, reject the specifier.
|
|
if (!desugared->canHaveNullability() &&
|
|
if (!desugared->canHaveNullability() &&
|
|
!(allowOnArrayType && desugared->isArrayType())) {
|
|
!(allowOnArrayType && desugared->isArrayType())) {
|
|
- S.Diag(nullabilityLoc, diag::err_nullability_nonpointer)
|
|
|
|
|
|
+ Diag(nullabilityLoc, diag::err_nullability_nonpointer)
|
|
<< DiagNullabilityKind(nullability, isContextSensitive) << type;
|
|
<< DiagNullabilityKind(nullability, isContextSensitive) << type;
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
@@ -6451,10 +6441,10 @@ static bool checkNullabilityTypeSpecifier(TypeProcessingState &state,
|
|
if (pointeeType->isAnyPointerType() ||
|
|
if (pointeeType->isAnyPointerType() ||
|
|
pointeeType->isObjCObjectPointerType() ||
|
|
pointeeType->isObjCObjectPointerType() ||
|
|
pointeeType->isMemberPointerType()) {
|
|
pointeeType->isMemberPointerType()) {
|
|
- S.Diag(nullabilityLoc, diag::err_nullability_cs_multilevel)
|
|
|
|
|
|
+ Diag(nullabilityLoc, diag::err_nullability_cs_multilevel)
|
|
<< DiagNullabilityKind(nullability, true)
|
|
<< DiagNullabilityKind(nullability, true)
|
|
<< type;
|
|
<< type;
|
|
- S.Diag(nullabilityLoc, diag::note_nullability_type_specifier)
|
|
|
|
|
|
+ Diag(nullabilityLoc, diag::note_nullability_type_specifier)
|
|
<< DiagNullabilityKind(nullability, false)
|
|
<< DiagNullabilityKind(nullability, false)
|
|
<< type
|
|
<< type
|
|
<< FixItHint::CreateReplacement(nullabilityLoc,
|
|
<< FixItHint::CreateReplacement(nullabilityLoc,
|
|
@@ -6464,21 +6454,16 @@ static bool checkNullabilityTypeSpecifier(TypeProcessingState &state,
|
|
}
|
|
}
|
|
|
|
|
|
// Form the attributed type.
|
|
// Form the attributed type.
|
|
- type = state.getAttributedType(
|
|
|
|
- createNullabilityAttr(S.Context, attr, nullability), type, type);
|
|
|
|
|
|
+ type = Context.getAttributedType(
|
|
|
|
+ AttributedType::getNullabilityAttrKind(nullability), type, type);
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
-/// Check the application of the Objective-C '__kindof' qualifier to
|
|
|
|
-/// the given type.
|
|
|
|
-static bool checkObjCKindOfType(TypeProcessingState &state, QualType &type,
|
|
|
|
- ParsedAttr &attr) {
|
|
|
|
- Sema &S = state.getSema();
|
|
|
|
-
|
|
|
|
|
|
+bool Sema::checkObjCKindOfType(QualType &type, SourceLocation loc) {
|
|
if (isa<ObjCTypeParamType>(type)) {
|
|
if (isa<ObjCTypeParamType>(type)) {
|
|
// Build the attributed type to record where __kindof occurred.
|
|
// Build the attributed type to record where __kindof occurred.
|
|
- type = state.getAttributedType(
|
|
|
|
- createSimpleAttr<ObjCKindOfAttr>(S.Context, attr), type, type);
|
|
|
|
|
|
+ type = Context.getAttributedType(AttributedType::attr_objc_kindof,
|
|
|
|
+ type, type);
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -6490,7 +6475,7 @@ static bool checkObjCKindOfType(TypeProcessingState &state, QualType &type,
|
|
// If not, we can't apply __kindof.
|
|
// If not, we can't apply __kindof.
|
|
if (!objType) {
|
|
if (!objType) {
|
|
// FIXME: Handle dependent types that aren't yet object types.
|
|
// FIXME: Handle dependent types that aren't yet object types.
|
|
- S.Diag(attr.getLoc(), diag::err_objc_kindof_nonobject)
|
|
|
|
|
|
+ Diag(loc, diag::err_objc_kindof_nonobject)
|
|
<< type;
|
|
<< type;
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
@@ -6498,31 +6483,45 @@ static bool checkObjCKindOfType(TypeProcessingState &state, QualType &type,
|
|
// Rebuild the "equivalent" type, which pushes __kindof down into
|
|
// Rebuild the "equivalent" type, which pushes __kindof down into
|
|
// the object type.
|
|
// the object type.
|
|
// There is no need to apply kindof on an unqualified id type.
|
|
// There is no need to apply kindof on an unqualified id type.
|
|
- QualType equivType = S.Context.getObjCObjectType(
|
|
|
|
|
|
+ QualType equivType = Context.getObjCObjectType(
|
|
objType->getBaseType(), objType->getTypeArgsAsWritten(),
|
|
objType->getBaseType(), objType->getTypeArgsAsWritten(),
|
|
objType->getProtocols(),
|
|
objType->getProtocols(),
|
|
/*isKindOf=*/objType->isObjCUnqualifiedId() ? false : true);
|
|
/*isKindOf=*/objType->isObjCUnqualifiedId() ? false : true);
|
|
|
|
|
|
// If we started with an object pointer type, rebuild it.
|
|
// If we started with an object pointer type, rebuild it.
|
|
if (ptrType) {
|
|
if (ptrType) {
|
|
- equivType = S.Context.getObjCObjectPointerType(equivType);
|
|
|
|
- if (auto nullability = type->getNullability(S.Context)) {
|
|
|
|
- // We create a nullability attribute from the __kindof attribute.
|
|
|
|
- // Make sure that will make sense.
|
|
|
|
- assert(attr.getAttributeSpellingListIndex() == 0 &&
|
|
|
|
- "multiple spellings for __kindof?");
|
|
|
|
- Attr *A = createNullabilityAttr(S.Context, attr, *nullability);
|
|
|
|
- A->setImplicit(true);
|
|
|
|
- equivType = state.getAttributedType(A, equivType, equivType);
|
|
|
|
|
|
+ equivType = Context.getObjCObjectPointerType(equivType);
|
|
|
|
+ if (auto nullability = type->getNullability(Context)) {
|
|
|
|
+ auto attrKind = AttributedType::getNullabilityAttrKind(*nullability);
|
|
|
|
+ equivType = Context.getAttributedType(attrKind, equivType, equivType);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Build the attributed type to record where __kindof occurred.
|
|
// Build the attributed type to record where __kindof occurred.
|
|
- type = state.getAttributedType(
|
|
|
|
- createSimpleAttr<ObjCKindOfAttr>(S.Context, attr), type, equivType);
|
|
|
|
|
|
+ type = Context.getAttributedType(AttributedType::attr_objc_kindof,
|
|
|
|
+ type,
|
|
|
|
+ equivType);
|
|
|
|
+
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/// Map a nullability attribute kind to a nullability kind.
|
|
|
|
+static NullabilityKind mapNullabilityAttrKind(ParsedAttr::Kind kind) {
|
|
|
|
+ switch (kind) {
|
|
|
|
+ case ParsedAttr::AT_TypeNonNull:
|
|
|
|
+ return NullabilityKind::NonNull;
|
|
|
|
+
|
|
|
|
+ case ParsedAttr::AT_TypeNullable:
|
|
|
|
+ return NullabilityKind::Nullable;
|
|
|
|
+
|
|
|
|
+ case ParsedAttr::AT_TypeNullUnspecified:
|
|
|
|
+ return NullabilityKind::Unspecified;
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ llvm_unreachable("not a nullability attribute kind");
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
/// Distribute a nullability type attribute that cannot be applied to
|
|
/// Distribute a nullability type attribute that cannot be applied to
|
|
/// the type specifier to a pointer, block pointer, or member pointer
|
|
/// the type specifier to a pointer, block pointer, or member pointer
|
|
/// declarator, complaining if necessary.
|
|
/// declarator, complaining if necessary.
|
|
@@ -6610,27 +6609,27 @@ static bool distributeNullabilityTypeAttr(TypeProcessingState &state,
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
-static Attr *getCCTypeAttr(ASTContext &Ctx, ParsedAttr &Attr) {
|
|
|
|
|
|
+static AttributedType::Kind getCCTypeAttrKind(ParsedAttr &Attr) {
|
|
assert(!Attr.isInvalid());
|
|
assert(!Attr.isInvalid());
|
|
switch (Attr.getKind()) {
|
|
switch (Attr.getKind()) {
|
|
default:
|
|
default:
|
|
llvm_unreachable("not a calling convention attribute");
|
|
llvm_unreachable("not a calling convention attribute");
|
|
case ParsedAttr::AT_CDecl:
|
|
case ParsedAttr::AT_CDecl:
|
|
- return createSimpleAttr<CDeclAttr>(Ctx, Attr);
|
|
|
|
|
|
+ return AttributedType::attr_cdecl;
|
|
case ParsedAttr::AT_FastCall:
|
|
case ParsedAttr::AT_FastCall:
|
|
- return createSimpleAttr<FastCallAttr>(Ctx, Attr);
|
|
|
|
|
|
+ return AttributedType::attr_fastcall;
|
|
case ParsedAttr::AT_StdCall:
|
|
case ParsedAttr::AT_StdCall:
|
|
- return createSimpleAttr<StdCallAttr>(Ctx, Attr);
|
|
|
|
|
|
+ return AttributedType::attr_stdcall;
|
|
case ParsedAttr::AT_ThisCall:
|
|
case ParsedAttr::AT_ThisCall:
|
|
- return createSimpleAttr<ThisCallAttr>(Ctx, Attr);
|
|
|
|
|
|
+ return AttributedType::attr_thiscall;
|
|
case ParsedAttr::AT_RegCall:
|
|
case ParsedAttr::AT_RegCall:
|
|
- return createSimpleAttr<RegCallAttr>(Ctx, Attr);
|
|
|
|
|
|
+ return AttributedType::attr_regcall;
|
|
case ParsedAttr::AT_Pascal:
|
|
case ParsedAttr::AT_Pascal:
|
|
- return createSimpleAttr<PascalAttr>(Ctx, Attr);
|
|
|
|
|
|
+ return AttributedType::attr_pascal;
|
|
case ParsedAttr::AT_SwiftCall:
|
|
case ParsedAttr::AT_SwiftCall:
|
|
- return createSimpleAttr<SwiftCallAttr>(Ctx, Attr);
|
|
|
|
|
|
+ return AttributedType::attr_swiftcall;
|
|
case ParsedAttr::AT_VectorCall:
|
|
case ParsedAttr::AT_VectorCall:
|
|
- return createSimpleAttr<VectorCallAttr>(Ctx, Attr);
|
|
|
|
|
|
+ return AttributedType::attr_vectorcall;
|
|
case ParsedAttr::AT_Pcs: {
|
|
case ParsedAttr::AT_Pcs: {
|
|
// The attribute may have had a fixit applied where we treated an
|
|
// The attribute may have had a fixit applied where we treated an
|
|
// identifier as a string literal. The contents of the string are valid,
|
|
// identifier as a string literal. The contents of the string are valid,
|
|
@@ -6640,22 +6639,20 @@ static Attr *getCCTypeAttr(ASTContext &Ctx, ParsedAttr &Attr) {
|
|
Str = cast<StringLiteral>(Attr.getArgAsExpr(0))->getString();
|
|
Str = cast<StringLiteral>(Attr.getArgAsExpr(0))->getString();
|
|
else
|
|
else
|
|
Str = Attr.getArgAsIdent(0)->Ident->getName();
|
|
Str = Attr.getArgAsIdent(0)->Ident->getName();
|
|
- PcsAttr::PCSType Type;
|
|
|
|
- if (!PcsAttr::ConvertStrToPCSType(Str, Type))
|
|
|
|
- llvm_unreachable("already validated the attribute");
|
|
|
|
- return ::new (Ctx) PcsAttr(Attr.getRange(), Ctx, Type,
|
|
|
|
- Attr.getAttributeSpellingListIndex());
|
|
|
|
|
|
+ return llvm::StringSwitch<AttributedType::Kind>(Str)
|
|
|
|
+ .Case("aapcs", AttributedType::attr_pcs)
|
|
|
|
+ .Case("aapcs-vfp", AttributedType::attr_pcs_vfp);
|
|
}
|
|
}
|
|
case ParsedAttr::AT_IntelOclBicc:
|
|
case ParsedAttr::AT_IntelOclBicc:
|
|
- return createSimpleAttr<IntelOclBiccAttr>(Ctx, Attr);
|
|
|
|
|
|
+ return AttributedType::attr_inteloclbicc;
|
|
case ParsedAttr::AT_MSABI:
|
|
case ParsedAttr::AT_MSABI:
|
|
- return createSimpleAttr<MSABIAttr>(Ctx, Attr);
|
|
|
|
|
|
+ return AttributedType::attr_ms_abi;
|
|
case ParsedAttr::AT_SysVABI:
|
|
case ParsedAttr::AT_SysVABI:
|
|
- return createSimpleAttr<SysVABIAttr>(Ctx, Attr);
|
|
|
|
|
|
+ return AttributedType::attr_sysv_abi;
|
|
case ParsedAttr::AT_PreserveMost:
|
|
case ParsedAttr::AT_PreserveMost:
|
|
- return createSimpleAttr<PreserveMostAttr>(Ctx, Attr);
|
|
|
|
|
|
+ return AttributedType::attr_preserve_most;
|
|
case ParsedAttr::AT_PreserveAll:
|
|
case ParsedAttr::AT_PreserveAll:
|
|
- return createSimpleAttr<PreserveAllAttr>(Ctx, Attr);
|
|
|
|
|
|
+ return AttributedType::attr_preserve_all;
|
|
}
|
|
}
|
|
llvm_unreachable("unexpected attribute kind!");
|
|
llvm_unreachable("unexpected attribute kind!");
|
|
}
|
|
}
|
|
@@ -6703,9 +6700,8 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, ParsedAttr &attr,
|
|
= unwrapped.get()->getExtInfo().withProducesResult(true);
|
|
= unwrapped.get()->getExtInfo().withProducesResult(true);
|
|
type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
|
|
type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
|
|
}
|
|
}
|
|
- type = state.getAttributedType(
|
|
|
|
- createSimpleAttr<NSReturnsRetainedAttr>(S.Context, attr),
|
|
|
|
- origType, type);
|
|
|
|
|
|
+ type = S.Context.getAttributedType(AttributedType::attr_ns_returns_retained,
|
|
|
|
+ origType, type);
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -6780,12 +6776,13 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, ParsedAttr &attr,
|
|
|
|
|
|
const FunctionType *fn = unwrapped.get();
|
|
const FunctionType *fn = unwrapped.get();
|
|
CallingConv CCOld = fn->getCallConv();
|
|
CallingConv CCOld = fn->getCallConv();
|
|
- Attr *CCAttr = getCCTypeAttr(S.Context, attr);
|
|
|
|
|
|
+ AttributedType::Kind CCAttrKind = getCCTypeAttrKind(attr);
|
|
|
|
|
|
if (CCOld != CC) {
|
|
if (CCOld != CC) {
|
|
// Error out on when there's already an attribute on the type
|
|
// Error out on when there's already an attribute on the type
|
|
// and the CCs don't match.
|
|
// and the CCs don't match.
|
|
- if (const AttributedType *AT = S.getCallingConvAttributedType(type)) {
|
|
|
|
|
|
+ const AttributedType *AT = S.getCallingConvAttributedType(type);
|
|
|
|
+ if (AT && AT->getAttrKind() != CCAttrKind) {
|
|
S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
|
|
S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
|
|
<< FunctionType::getNameForCallConv(CC)
|
|
<< FunctionType::getNameForCallConv(CC)
|
|
<< FunctionType::getNameForCallConv(CCOld);
|
|
<< FunctionType::getNameForCallConv(CCOld);
|
|
@@ -6839,7 +6836,7 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, ParsedAttr &attr,
|
|
Equivalent =
|
|
Equivalent =
|
|
unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
|
|
unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
|
|
}
|
|
}
|
|
- type = state.getAttributedType(CCAttr, type, Equivalent);
|
|
|
|
|
|
+ type = S.Context.getAttributedType(CCAttrKind, type, Equivalent);
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -7195,15 +7192,14 @@ static void deduceOpenCLImplicitAddrSpace(TypeProcessingState &State,
|
|
T = State.getSema().Context.getAddrSpaceQualType(T, ImpAddr);
|
|
T = State.getSema().Context.getAddrSpaceQualType(T, ImpAddr);
|
|
}
|
|
}
|
|
|
|
|
|
-static void HandleLifetimeBoundAttr(TypeProcessingState &State,
|
|
|
|
- QualType &CurType,
|
|
|
|
- ParsedAttr &Attr) {
|
|
|
|
- if (State.getDeclarator().isDeclarationOfFunction()) {
|
|
|
|
- CurType = State.getAttributedType(
|
|
|
|
- createSimpleAttr<LifetimeBoundAttr>(State.getSema().Context, Attr),
|
|
|
|
- CurType, CurType);
|
|
|
|
|
|
+static void HandleLifetimeBoundAttr(QualType &CurType,
|
|
|
|
+ const ParsedAttr &Attr,
|
|
|
|
+ Sema &S, Declarator &D) {
|
|
|
|
+ if (D.isDeclarationOfFunction()) {
|
|
|
|
+ CurType = S.Context.getAttributedType(AttributedType::attr_lifetimebound,
|
|
|
|
+ CurType, CurType);
|
|
} else {
|
|
} else {
|
|
- Attr.diagnoseAppertainsTo(State.getSema(), nullptr);
|
|
|
|
|
|
+ Attr.diagnoseAppertainsTo(S, nullptr);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -7313,8 +7309,11 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
|
|
attr.setUsedAsTypeAttr();
|
|
attr.setUsedAsTypeAttr();
|
|
break;
|
|
break;
|
|
case ParsedAttr::AT_LifetimeBound:
|
|
case ParsedAttr::AT_LifetimeBound:
|
|
- if (TAL == TAL_DeclChunk)
|
|
|
|
- HandleLifetimeBoundAttr(state, type, attr);
|
|
|
|
|
|
+ if (TAL == TAL_DeclChunk) {
|
|
|
|
+ HandleLifetimeBoundAttr(type, attr, state.getSema(),
|
|
|
|
+ state.getDeclarator());
|
|
|
|
+ attr.setUsedAsTypeAttr();
|
|
|
|
+ }
|
|
break;
|
|
break;
|
|
|
|
|
|
MS_TYPE_ATTRS_CASELIST:
|
|
MS_TYPE_ATTRS_CASELIST:
|
|
@@ -7338,10 +7337,11 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
|
|
bool allowOnArrayType =
|
|
bool allowOnArrayType =
|
|
state.getDeclarator().isPrototypeContext() &&
|
|
state.getDeclarator().isPrototypeContext() &&
|
|
!hasOuterPointerLikeChunk(state.getDeclarator(), endIndex);
|
|
!hasOuterPointerLikeChunk(state.getDeclarator(), endIndex);
|
|
- if (checkNullabilityTypeSpecifier(
|
|
|
|
- state,
|
|
|
|
|
|
+ if (state.getSema().checkNullabilityTypeSpecifier(
|
|
type,
|
|
type,
|
|
- attr,
|
|
|
|
|
|
+ mapNullabilityAttrKind(attr.getKind()),
|
|
|
|
+ attr.getLoc(),
|
|
|
|
+ attr.isContextSensitiveKeywordAttribute(),
|
|
allowOnArrayType)) {
|
|
allowOnArrayType)) {
|
|
attr.setInvalid();
|
|
attr.setInvalid();
|
|
}
|
|
}
|
|
@@ -7368,8 +7368,9 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
|
|
}
|
|
}
|
|
|
|
|
|
// Apply it regardless.
|
|
// Apply it regardless.
|
|
- if (checkObjCKindOfType(state, type, attr))
|
|
|
|
|
|
+ if (state.getSema().checkObjCKindOfType(type, attr.getLoc()))
|
|
attr.setInvalid();
|
|
attr.setInvalid();
|
|
|
|
+ attr.setUsedAsTypeAttr();
|
|
break;
|
|
break;
|
|
|
|
|
|
FUNCTION_TYPE_ATTRS_CASELIST:
|
|
FUNCTION_TYPE_ATTRS_CASELIST:
|