diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 10 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 8 | ||||
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaObjCProperty.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 521 | ||||
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 21 |
6 files changed, 284 insertions, 282 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index e62728c124c..abdeba60be7 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -5999,14 +5999,14 @@ static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) { // The [[lifetimebound]] attribute can be applied to the implicit object // parameter of a non-static member function (other than a ctor or dtor) // by applying it to the function type. - if (const auto *A = ATL.getAttrAs<LifetimeBoundAttr>()) { + if (ATL.getAttrKind() == AttributedType::attr_lifetimebound) { const auto *MD = dyn_cast<CXXMethodDecl>(FD); if (!MD || MD->isStatic()) { - S.Diag(A->getLocation(), diag::err_lifetimebound_no_object_param) - << !MD << A->getRange(); + S.Diag(ATL.getAttrNameLoc(), diag::err_lifetimebound_no_object_param) + << !MD << ATL.getLocalSourceRange(); } else if (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)) { - S.Diag(A->getLocation(), diag::err_lifetimebound_ctor_dtor) - << isa<CXXDestructorDecl>(MD) << A->getRange(); + S.Diag(ATL.getAttrNameLoc(), diag::err_lifetimebound_ctor_dtor) + << isa<CXXDestructorDecl>(MD) << ATL.getLocalSourceRange(); } } } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index baa114b350a..1259d25629b 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -14658,15 +14658,15 @@ static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var, // Warn about implicitly autoreleasing indirect parameters captured by blocks. if (const auto *PT = CaptureType->getAs<PointerType>()) { // This function finds out whether there is an AttributedType of kind - // attr::ObjCOwnership in Ty. The existence of AttributedType of kind - // attr::ObjCOwnership implies __autoreleasing was explicitly specified + // attr_objc_ownership in Ty. The existence of AttributedType of kind + // attr_objc_ownership implies __autoreleasing was explicitly specified // rather than being added implicitly by the compiler. auto IsObjCOwnershipAttributedType = [](QualType Ty) { while (const auto *AttrTy = Ty->getAs<AttributedType>()) { - if (AttrTy->getAttrKind() == attr::ObjCOwnership) + if (AttrTy->getAttrKind() == AttributedType::attr_objc_ownership) return true; - // Peel off AttributedTypes that are not of kind ObjCOwnership. + // Peel off AttributedTypes that are not of kind objc_ownership. Ty = AttrTy->getModifiedType(); } diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 0d3e3d4c47a..766f23b05b0 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -6360,7 +6360,7 @@ static bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD) { for (TypeLoc TL = TSI->getTypeLoc(); (ATL = TL.getAsAdjusted<AttributedTypeLoc>()); TL = ATL.getModifiedLoc()) { - if (ATL.getAttrAs<LifetimeBoundAttr>()) + if (ATL.getAttrKind() == AttributedType::attr_lifetimebound) return true; } return false; diff --git a/clang/lib/Sema/SemaObjCProperty.cpp b/clang/lib/Sema/SemaObjCProperty.cpp index ab7b83c4c33..3aad25b73a7 100644 --- a/clang/lib/Sema/SemaObjCProperty.cpp +++ b/clang/lib/Sema/SemaObjCProperty.cpp @@ -2384,7 +2384,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property) { QualType modifiedTy = resultTy; if (auto nullability = AttributedType::stripOuterNullability(modifiedTy)) { if (*nullability == NullabilityKind::Unspecified) - resultTy = Context.getAttributedType(attr::TypeNonNull, + resultTy = Context.getAttributedType(AttributedType::attr_nonnull, modifiedTy, modifiedTy); } } @@ -2458,7 +2458,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property) { QualType modifiedTy = paramTy; if (auto nullability = AttributedType::stripOuterNullability(modifiedTy)){ if (*nullability == NullabilityKind::Unspecified) - paramTy = Context.getAttributedType(attr::TypeNullable, + paramTy = Context.getAttributedType(AttributedType::attr_nullable, modifiedTy, modifiedTy); } } diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index bad66162491..486d8ac4ed0 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -172,16 +172,6 @@ namespace { /// processing is complete. 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: TypeProcessingState(Sema &sema, Declarator &declarator) : sema(sema), declarator(declarator), @@ -240,43 +230,6 @@ namespace { 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() { if (trivial) return; @@ -3879,32 +3832,6 @@ static bool hasOuterPointerLikeChunk(const Declarator &D, unsigned endIndex) { 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, QualType declSpecType, TypeSourceInfo *TInfo) { @@ -4257,8 +4184,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, pointerKind, D.getDeclSpec().getTypeSpecTypeLoc(), D.getDeclSpec().getEndLoc(), 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()) return Context.getTrivialTypeSourceInfo(T); - return GetTypeSourceInfoForDeclarator(state, T, TInfo); + return S.GetTypeSourceInfoForDeclarator(D, T, TInfo); } /// GetTypeForDeclarator - Convert the type for the specified @@ -5233,25 +5161,131 @@ TypeSourceInfo *Sema::GetTypeForDeclaratorCast(Declarator &D, QualType FromTy) { 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, - 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 { class TypeSpecLocFiller : public TypeLocVisitor<TypeSpecLocFiller> { ASTContext &Context; - TypeProcessingState &State; const DeclSpec &DS; 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) { + fillAttributedTypeLoc(TL, DS.getAttributes(), ParsedAttributesView{}); Visit(TL.getModifiedLoc()); - fillAttributedTypeLoc(TL, State); } void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { Visit(TL.getUnqualifiedLoc()); @@ -5408,13 +5442,11 @@ namespace { class DeclaratorLocFiller : public TypeLocVisitor<DeclaratorLocFiller> { ASTContext &Context; - TypeProcessingState &State; const DeclaratorChunk &Chunk; 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) { llvm_unreachable("qualified type locs not expected here!"); @@ -5424,7 +5456,7 @@ namespace { } void VisitAttributedTypeLoc(AttributedTypeLoc TL) { - fillAttributedTypeLoc(TL, State); + fillAttributedTypeLoc(TL, Chunk.getAttrs(), ParsedAttributesView{}); } void VisitAdjustedTypeLoc(AdjustedTypeLoc TL) { // nothing @@ -5581,13 +5613,10 @@ fillDependentAddressSpaceTypeLoc(DependentAddressSpaceTypeLoc DASTL, /// up in the normal place in the declaration specifiers (such as a C++ /// conversion function), this pointer will refer to a type source information /// 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(); // 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) { + if (DependentAddressSpaceTypeLoc DASTL = CurrTL.getAs<DependentAddressSpaceTypeLoc>()) { fillDependentAddressSpaceTypeLoc(DASTL, D.getTypeObject(i).getAttrs()); @@ -5611,7 +5641,8 @@ GetTypeSourceInfoForDeclarator(TypeProcessingState &State, } while (AttributedTypeLoc TL = CurrTL.getAs<AttributedTypeLoc>()) { - fillAttributedTypeLoc(TL, State); + fillAttributedTypeLoc(TL, D.getTypeObject(i).getAttrs(), + D.getAttributes()); CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc(); } @@ -5619,7 +5650,7 @@ GetTypeSourceInfoForDeclarator(TypeProcessingState &State, while (AdjustedTypeLoc TL = CurrTL.getAs<AdjustedTypeLoc>()) CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc(); - DeclaratorLocFiller(S.Context, State, D.getTypeObject(i)).Visit(CurrTL); + DeclaratorLocFiller(Context, D.getTypeObject(i)).Visit(CurrTL); CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc(); } @@ -5630,7 +5661,7 @@ GetTypeSourceInfoForDeclarator(TypeProcessingState &State, assert(TL.getFullDataSize() == CurrTL.getFullDataSize()); memcpy(CurrTL.getOpaqueData(), TL.getOpaqueData(), TL.getFullDataSize()); } else { - TypeSpecLocFiller(S.Context, State, D.getDeclSpec()).Visit(CurrTL); + TypeSpecLocFiller(Context, D.getDeclSpec()).Visit(CurrTL); } return TInfo; @@ -5859,7 +5890,7 @@ static bool hasDirectOwnershipQualifier(QualType type) { while (true) { // __strong id if (const AttributedType *attr = dyn_cast<AttributedType>(type)) { - if (attr->getAttrKind() == attr::ObjCOwnership) + if (attr->getAttrKind() == AttributedType::attr_objc_ownership) return true; type = attr->getModifiedType(); @@ -6003,9 +6034,9 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state, // the coexistence problems with __unsafe_unretained. if (!S.getLangOpts().ObjCAutoRefCount && 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; } @@ -6015,12 +6046,9 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state, // If we have a valid source location for the attribute, use an // 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, unsigned diagnostic, QualType type) { @@ -6120,10 +6148,8 @@ static bool handleObjCGCTypeAttr(TypeProcessingState &state, ParsedAttr &attr, // Make an attributed type to preserve the source information. 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; } @@ -6266,50 +6292,37 @@ namespace { } // end anonymous namespace static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State, - ParsedAttr &PAttr, QualType &Type) { + ParsedAttr &Attr, QualType &Type) { 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; const AttributedType *AT = dyn_cast<AttributedType>(Type); while (AT) { - attr::Kind CurAttrKind = AT->getAttrKind(); + AttributedType::Kind CurAttrKind = AT->getAttrKind(); // You cannot specify duplicate type attributes, so if the attribute has // 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; } // You cannot have both __sptr and __uptr on the same type, nor can you // 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'"; 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'"; return true; } @@ -6320,64 +6333,41 @@ static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State, // Pointer type qualifiers can only operate on pointer types, but not // 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 (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 - S.Diag(PAttr.getLoc(), diag::err_attribute_pointers_only) << PAttr << 0; + S.Diag(Attr.getLoc(), diag::err_attribute_pointers_only) << Attr << 0; 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. QualType desugared = type; @@ -6386,7 +6376,7 @@ static bool checkNullabilityTypeSpecifier(TypeProcessingState &state, if (auto existingNullability = attributed->getImmediateNullability()) { // Duplicated nullability. if (nullability == *existingNullability) { - S.Diag(nullabilityLoc, diag::warn_nullability_duplicate) + Diag(nullabilityLoc, diag::warn_nullability_duplicate) << DiagNullabilityKind(nullability, isContextSensitive) << FixItHint::CreateRemoval(nullabilityLoc); @@ -6394,7 +6384,7 @@ static bool checkNullabilityTypeSpecifier(TypeProcessingState &state, } // Conflicting nullability. - S.Diag(nullabilityLoc, diag::err_nullability_conflicting) + Diag(nullabilityLoc, diag::err_nullability_conflicting) << DiagNullabilityKind(nullability, isContextSensitive) << DiagNullabilityKind(*existingNullability, false); return true; @@ -6407,9 +6397,9 @@ static bool checkNullabilityTypeSpecifier(TypeProcessingState &state, // This (unlike the code above) looks through typedefs that might // have nullability specifiers on them, which means we cannot // provide a useful Fix-It. - if (auto existingNullability = desugared->getNullability(S.Context)) { + if (auto existingNullability = desugared->getNullability(Context)) { if (nullability != *existingNullability) { - S.Diag(nullabilityLoc, diag::err_nullability_conflicting) + Diag(nullabilityLoc, diag::err_nullability_conflicting) << DiagNullabilityKind(nullability, isContextSensitive) << DiagNullabilityKind(*existingNullability, false); @@ -6420,7 +6410,7 @@ static bool checkNullabilityTypeSpecifier(TypeProcessingState &state, if (auto typedefNullability = AttributedType::stripOuterNullability(underlyingType)) { if (*typedefNullability == *existingNullability) { - S.Diag(typedefDecl->getLocation(), diag::note_nullability_here) + Diag(typedefDecl->getLocation(), diag::note_nullability_here) << DiagNullabilityKind(*existingNullability, false); } } @@ -6433,7 +6423,7 @@ static bool checkNullabilityTypeSpecifier(TypeProcessingState &state, // If this definitely isn't a pointer type, reject the specifier. if (!desugared->canHaveNullability() && !(allowOnArrayType && desugared->isArrayType())) { - S.Diag(nullabilityLoc, diag::err_nullability_nonpointer) + Diag(nullabilityLoc, diag::err_nullability_nonpointer) << DiagNullabilityKind(nullability, isContextSensitive) << type; return true; } @@ -6451,10 +6441,10 @@ static bool checkNullabilityTypeSpecifier(TypeProcessingState &state, if (pointeeType->isAnyPointerType() || pointeeType->isObjCObjectPointerType() || pointeeType->isMemberPointerType()) { - S.Diag(nullabilityLoc, diag::err_nullability_cs_multilevel) + Diag(nullabilityLoc, diag::err_nullability_cs_multilevel) << DiagNullabilityKind(nullability, true) << type; - S.Diag(nullabilityLoc, diag::note_nullability_type_specifier) + Diag(nullabilityLoc, diag::note_nullability_type_specifier) << DiagNullabilityKind(nullability, false) << type << FixItHint::CreateReplacement(nullabilityLoc, @@ -6464,21 +6454,16 @@ static bool checkNullabilityTypeSpecifier(TypeProcessingState &state, } // Form the attributed type. - type = state.getAttributedType( - createNullabilityAttr(S.Context, attr, nullability), type, type); + type = Context.getAttributedType( + AttributedType::getNullabilityAttrKind(nullability), type, type); 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)) { // 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; } @@ -6490,7 +6475,7 @@ static bool checkObjCKindOfType(TypeProcessingState &state, QualType &type, // If not, we can't apply __kindof. if (!objType) { // 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; return true; } @@ -6498,31 +6483,45 @@ static bool checkObjCKindOfType(TypeProcessingState &state, QualType &type, // Rebuild the "equivalent" type, which pushes __kindof down into // the object 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->getProtocols(), /*isKindOf=*/objType->isObjCUnqualifiedId() ? false : true); // If we started with an object pointer type, rebuild it. 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. - type = state.getAttributedType( - createSimpleAttr<ObjCKindOfAttr>(S.Context, attr), type, equivType); + type = Context.getAttributedType(AttributedType::attr_objc_kindof, + type, + equivType); + 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 /// the type specifier to a pointer, block pointer, or member pointer /// declarator, complaining if necessary. @@ -6610,27 +6609,27 @@ static bool distributeNullabilityTypeAttr(TypeProcessingState &state, return false; } -static Attr *getCCTypeAttr(ASTContext &Ctx, ParsedAttr &Attr) { +static AttributedType::Kind getCCTypeAttrKind(ParsedAttr &Attr) { assert(!Attr.isInvalid()); switch (Attr.getKind()) { default: llvm_unreachable("not a calling convention attribute"); case ParsedAttr::AT_CDecl: - return createSimpleAttr<CDeclAttr>(Ctx, Attr); + return AttributedType::attr_cdecl; case ParsedAttr::AT_FastCall: - return createSimpleAttr<FastCallAttr>(Ctx, Attr); + return AttributedType::attr_fastcall; case ParsedAttr::AT_StdCall: - return createSimpleAttr<StdCallAttr>(Ctx, Attr); + return AttributedType::attr_stdcall; case ParsedAttr::AT_ThisCall: - return createSimpleAttr<ThisCallAttr>(Ctx, Attr); + return AttributedType::attr_thiscall; case ParsedAttr::AT_RegCall: - return createSimpleAttr<RegCallAttr>(Ctx, Attr); + return AttributedType::attr_regcall; case ParsedAttr::AT_Pascal: - return createSimpleAttr<PascalAttr>(Ctx, Attr); + return AttributedType::attr_pascal; case ParsedAttr::AT_SwiftCall: - return createSimpleAttr<SwiftCallAttr>(Ctx, Attr); + return AttributedType::attr_swiftcall; case ParsedAttr::AT_VectorCall: - return createSimpleAttr<VectorCallAttr>(Ctx, Attr); + return AttributedType::attr_vectorcall; case ParsedAttr::AT_Pcs: { // The attribute may have had a fixit applied where we treated an // 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(); else 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: - return createSimpleAttr<IntelOclBiccAttr>(Ctx, Attr); + return AttributedType::attr_inteloclbicc; case ParsedAttr::AT_MSABI: - return createSimpleAttr<MSABIAttr>(Ctx, Attr); + return AttributedType::attr_ms_abi; case ParsedAttr::AT_SysVABI: - return createSimpleAttr<SysVABIAttr>(Ctx, Attr); + return AttributedType::attr_sysv_abi; case ParsedAttr::AT_PreserveMost: - return createSimpleAttr<PreserveMostAttr>(Ctx, Attr); + return AttributedType::attr_preserve_most; case ParsedAttr::AT_PreserveAll: - return createSimpleAttr<PreserveAllAttr>(Ctx, Attr); + return AttributedType::attr_preserve_all; } llvm_unreachable("unexpected attribute kind!"); } @@ -6703,9 +6700,8 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, ParsedAttr &attr, = unwrapped.get()->getExtInfo().withProducesResult(true); 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; } @@ -6780,12 +6776,13 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, ParsedAttr &attr, const FunctionType *fn = unwrapped.get(); CallingConv CCOld = fn->getCallConv(); - Attr *CCAttr = getCCTypeAttr(S.Context, attr); + AttributedType::Kind CCAttrKind = getCCTypeAttrKind(attr); if (CCOld != CC) { // Error out on when there's already an attribute on the type // 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) << FunctionType::getNameForCallConv(CC) << FunctionType::getNameForCallConv(CCOld); @@ -6839,7 +6836,7 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, ParsedAttr &attr, Equivalent = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI)); } - type = state.getAttributedType(CCAttr, type, Equivalent); + type = S.Context.getAttributedType(CCAttrKind, type, Equivalent); return true; } @@ -7195,15 +7192,14 @@ static void deduceOpenCLImplicitAddrSpace(TypeProcessingState &State, 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 { - Attr.diagnoseAppertainsTo(State.getSema(), nullptr); + Attr.diagnoseAppertainsTo(S, nullptr); } } @@ -7313,8 +7309,11 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, attr.setUsedAsTypeAttr(); break; 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; MS_TYPE_ATTRS_CASELIST: @@ -7338,10 +7337,11 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, bool allowOnArrayType = state.getDeclarator().isPrototypeContext() && !hasOuterPointerLikeChunk(state.getDeclarator(), endIndex); - if (checkNullabilityTypeSpecifier( - state, + if (state.getSema().checkNullabilityTypeSpecifier( type, - attr, + mapNullabilityAttrKind(attr.getKind()), + attr.getLoc(), + attr.isContextSensitiveKeywordAttribute(), allowOnArrayType)) { attr.setInvalid(); } @@ -7368,8 +7368,9 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, } // Apply it regardless. - if (checkObjCKindOfType(state, type, attr)) + if (state.getSema().checkObjCKindOfType(type, attr.getLoc())) attr.setInvalid(); + attr.setUsedAsTypeAttr(); break; FUNCTION_TYPE_ATTRS_CASELIST: diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 98256d66a2a..d680e6be6d3 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -6058,11 +6058,6 @@ QualType TreeTransform<Derived>::TransformAttributedType( if (modifiedType.isNull()) return QualType(); - const Attr *oldAttr = TL.getAttr(); - const Attr *newAttr = getDerived().TransformAttr(oldAttr); - if (!newAttr) - return QualType(); - QualType result = TL.getType(); // FIXME: dependent operand expressions? @@ -6079,20 +6074,26 @@ QualType TreeTransform<Derived>::TransformAttributedType( // type sugar, and therefore cannot be diagnosed in any other way. if (auto nullability = oldType->getImmediateNullability()) { if (!modifiedType->canHaveNullability()) { - SemaRef.Diag(TL.getAttr()->getLocation(), - diag::err_nullability_nonpointer) - << DiagNullabilityKind(*nullability, false) << modifiedType; + SemaRef.Diag(TL.getAttrNameLoc(), diag::err_nullability_nonpointer) + << DiagNullabilityKind(*nullability, false) << modifiedType; return QualType(); } } - result = SemaRef.Context.getAttributedType(newAttr->getKind(), + result = SemaRef.Context.getAttributedType(oldType->getAttrKind(), modifiedType, equivalentType); } AttributedTypeLoc newTL = TLB.push<AttributedTypeLoc>(result); - newTL.setAttr(newAttr); + newTL.setAttrNameLoc(TL.getAttrNameLoc()); + if (TL.hasAttrOperand()) + newTL.setAttrOperandParensRange(TL.getAttrOperandParensRange()); + if (TL.hasAttrExprOperand()) + newTL.setAttrExprOperand(TL.getAttrExprOperand()); + else if (TL.hasAttrEnumOperand()) + newTL.setAttrEnumOperandLoc(TL.getAttrEnumOperandLoc()); + return result; } |