r340215 - Model type attributes as regular Attrs.
Mikael Holmén via cfe-commits
cfe-commits at lists.llvm.org
Mon Aug 20 23:11:43 PDT 2018
Hi,
I get a warning with this:
[1/16] Building CXX object
tools/clang/lib/Sema/CMakeFiles/clangSema.dir/SemaType.cpp.o
../tools/clang/lib/Sema/SemaType.cpp: In function 'bool
handleFunctionTypeAttr({anonymous}::TypeProcessingState&,
clang::ParsedAttr&, clang::QualType&)':
../tools/clang/lib/Sema/SemaType.cpp:6788:31: warning: unused variable
'AT' [-Wunused-variable]
if (const AttributedType *AT = S.getCallingConvAttributedType(type)) {
^
/Mikael
On 08/20/2018 11:47 PM, Richard Smith via cfe-commits wrote:
> Author: rsmith
> Date: Mon Aug 20 14:47:29 2018
> New Revision: 340215
>
> URL: http://llvm.org/viewvc/llvm-project?rev=340215&view=rev
> Log:
> Model type attributes as regular Attrs.
>
> Specifically, AttributedType now tracks a regular attr::Kind rather than
> having its own parallel Kind enumeration, and AttributedTypeLoc now
> holds an Attr* instead of holding an ad-hoc collection of Attr fields.
>
> Differential Revision: https://reviews.llvm.org/D50526
>
> This reinstates r339623, reverted in r339638, with a fix to not fail
> template instantiation if we instantiate a QualType with no associated
> type source information and we encounter an AttributedType.
>
> Modified:
> cfe/trunk/include/clang/AST/ASTContext.h
> cfe/trunk/include/clang/AST/Attr.h
> cfe/trunk/include/clang/AST/Type.h
> cfe/trunk/include/clang/AST/TypeLoc.h
> cfe/trunk/include/clang/Basic/Attr.td
> cfe/trunk/include/clang/Sema/Sema.h
> cfe/trunk/include/clang/Serialization/ASTReader.h
> cfe/trunk/include/clang/Serialization/ASTWriter.h
> cfe/trunk/lib/ARCMigrate/TransGCAttrs.cpp
> cfe/trunk/lib/ARCMigrate/Transforms.cpp
> cfe/trunk/lib/AST/ASTContext.cpp
> cfe/trunk/lib/AST/Type.cpp
> cfe/trunk/lib/AST/TypeLoc.cpp
> cfe/trunk/lib/AST/TypePrinter.cpp
> cfe/trunk/lib/Sema/SemaDecl.cpp
> cfe/trunk/lib/Sema/SemaExpr.cpp
> cfe/trunk/lib/Sema/SemaInit.cpp
> cfe/trunk/lib/Sema/SemaObjCProperty.cpp
> cfe/trunk/lib/Sema/SemaType.cpp
> cfe/trunk/lib/Sema/TreeTransform.h
> cfe/trunk/lib/Serialization/ASTReader.cpp
> cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
> cfe/trunk/lib/Serialization/ASTWriter.cpp
> cfe/trunk/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
> cfe/trunk/test/SemaCXX/calling-conv-compat.cpp
> cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
>
> Modified: cfe/trunk/include/clang/AST/ASTContext.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=340215&r1=340214&r2=340215&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/ASTContext.h (original)
> +++ cfe/trunk/include/clang/AST/ASTContext.h Mon Aug 20 14:47:29 2018
> @@ -31,6 +31,7 @@
> #include "clang/AST/TemplateName.h"
> #include "clang/AST/Type.h"
> #include "clang/Basic/AddressSpaces.h"
> +#include "clang/Basic/AttrKinds.h"
> #include "clang/Basic/IdentifierTable.h"
> #include "clang/Basic/LLVM.h"
> #include "clang/Basic/LangOptions.h"
> @@ -1422,7 +1423,7 @@ public:
>
> QualType getInjectedClassNameType(CXXRecordDecl *Decl, QualType TST) const;
>
> - QualType getAttributedType(AttributedType::Kind attrKind,
> + QualType getAttributedType(attr::Kind attrKind,
> QualType modifiedType,
> QualType equivalentType);
>
>
> Modified: cfe/trunk/include/clang/AST/Attr.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Attr.h?rev=340215&r1=340214&r2=340215&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/Attr.h (original)
> +++ cfe/trunk/include/clang/AST/Attr.h Mon Aug 20 14:47:29 2018
> @@ -113,6 +113,19 @@ public:
> void printPretty(raw_ostream &OS, const PrintingPolicy &Policy) const;
> };
>
> +class TypeAttr : public Attr {
> +protected:
> + TypeAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
> + bool IsLateParsed)
> + : Attr(AK, R, SpellingListIndex, IsLateParsed) {}
> +
> +public:
> + static bool classof(const Attr *A) {
> + return A->getKind() >= attr::FirstTypeAttr &&
> + A->getKind() <= attr::LastTypeAttr;
> + }
> +};
> +
> class StmtAttr : public Attr {
> protected:
> StmtAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
>
> Modified: cfe/trunk/include/clang/AST/Type.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=340215&r1=340214&r2=340215&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/Type.h (original)
> +++ cfe/trunk/include/clang/AST/Type.h Mon Aug 20 14:47:29 2018
> @@ -21,6 +21,7 @@
> #include "clang/AST/NestedNameSpecifier.h"
> #include "clang/AST/TemplateName.h"
> #include "clang/Basic/AddressSpaces.h"
> +#include "clang/Basic/AttrKinds.h"
> #include "clang/Basic/Diagnostic.h"
> #include "clang/Basic/ExceptionSpecificationType.h"
> #include "clang/Basic/LLVM.h"
> @@ -1970,7 +1971,16 @@ public:
> bool isObjCQualifiedClassType() const; // Class<foo>
> bool isObjCObjectOrInterfaceType() const;
> bool isObjCIdType() const; // id
> - bool isObjCInertUnsafeUnretainedType() const;
> +
> + /// Was this type written with the special inert-in-ARC __unsafe_unretained
> + /// qualifier?
> + ///
> + /// This approximates the answer to the following question: if this
> + /// translation unit were compiled in ARC, would this type be qualified
> + /// with __unsafe_unretained?
> + bool isObjCInertUnsafeUnretainedType() const {
> + return hasAttr(attr::ObjCInertUnsafeUnretained);
> + }
>
> /// Whether the type is Objective-C 'id' or a __kindof type of an
> /// object type, e.g., __kindof NSView * or __kindof id
> @@ -2184,6 +2194,10 @@ public:
> /// qualifiers from the outermost type.
> const ArrayType *castAsArrayTypeUnsafe() const;
>
> + /// Determine whether this type had the specified attribute applied to it
> + /// (looking through top-level type sugar).
> + bool hasAttr(attr::Kind AK) const;
> +
> /// Get the base element type of this type, potentially discarding type
> /// qualifiers. This should never be used when type qualifiers
> /// are meaningful.
> @@ -4293,56 +4307,7 @@ public:
> /// - the canonical type is VectorType(16, int)
> class AttributedType : public Type, public llvm::FoldingSetNode {
> public:
> - // It is really silly to have yet another attribute-kind enum, but
> - // clang::attr::Kind doesn't currently cover the pure type attrs.
> - enum Kind {
> - // Expression operand.
> - attr_address_space,
> - attr_regparm,
> - attr_vector_size,
> - attr_neon_vector_type,
> - attr_neon_polyvector_type,
> -
> - FirstExprOperandKind = attr_address_space,
> - LastExprOperandKind = attr_neon_polyvector_type,
> -
> - // Enumerated operand (string or keyword).
> - attr_objc_gc,
> - attr_objc_ownership,
> - attr_pcs,
> - attr_pcs_vfp,
> -
> - FirstEnumOperandKind = attr_objc_gc,
> - LastEnumOperandKind = attr_pcs_vfp,
> -
> - // No operand.
> - attr_noreturn,
> - attr_nocf_check,
> - attr_cdecl,
> - attr_fastcall,
> - attr_stdcall,
> - attr_thiscall,
> - attr_regcall,
> - attr_pascal,
> - attr_swiftcall,
> - attr_vectorcall,
> - attr_inteloclbicc,
> - attr_ms_abi,
> - attr_sysv_abi,
> - attr_preserve_most,
> - attr_preserve_all,
> - attr_ptr32,
> - attr_ptr64,
> - attr_sptr,
> - attr_uptr,
> - attr_nonnull,
> - attr_ns_returns_retained,
> - attr_nullable,
> - attr_null_unspecified,
> - attr_objc_kindof,
> - attr_objc_inert_unsafe_unretained,
> - attr_lifetimebound,
> - };
> + using Kind = attr::Kind;
>
> private:
> friend class ASTContext; // ASTContext creates these
> @@ -4350,7 +4315,7 @@ private:
> QualType ModifiedType;
> QualType EquivalentType;
>
> - AttributedType(QualType canon, Kind attrKind, QualType modified,
> + AttributedType(QualType canon, attr::Kind attrKind, QualType modified,
> QualType equivalent)
> : Type(Attributed, canon, equivalent->isDependentType(),
> equivalent->isInstantiationDependentType(),
> @@ -4399,13 +4364,13 @@ public:
> static Kind getNullabilityAttrKind(NullabilityKind kind) {
> switch (kind) {
> case NullabilityKind::NonNull:
> - return attr_nonnull;
> + return attr::TypeNonNull;
>
> case NullabilityKind::Nullable:
> - return attr_nullable;
> + return attr::TypeNullable;
>
> case NullabilityKind::Unspecified:
> - return attr_null_unspecified;
> + return attr::TypeNullUnspecified;
> }
> llvm_unreachable("Unknown nullability kind.");
> }
>
> Modified: cfe/trunk/include/clang/AST/TypeLoc.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TypeLoc.h?rev=340215&r1=340214&r2=340215&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/TypeLoc.h (original)
> +++ cfe/trunk/include/clang/AST/TypeLoc.h Mon Aug 20 14:47:29 2018
> @@ -15,6 +15,7 @@
> #ifndef LLVM_CLANG_AST_TYPELOC_H
> #define LLVM_CLANG_AST_TYPELOC_H
>
> +#include "clang/AST/Attr.h"
> #include "clang/AST/Decl.h"
> #include "clang/AST/NestedNameSpecifier.h"
> #include "clang/AST/TemplateBase.h"
> @@ -849,16 +850,7 @@ class SubstTemplateTypeParmPackTypeLoc :
> };
>
> struct AttributedLocInfo {
> - union {
> - Expr *ExprOperand;
> -
> - /// A raw SourceLocation.
> - unsigned EnumOperandLoc;
> - };
> -
> - SourceRange OperandParens;
> -
> - SourceLocation AttrLoc;
> + const Attr *TypeAttr;
> };
>
> /// Type source information for an attributed type.
> @@ -867,24 +859,10 @@ class AttributedTypeLoc : public Concret
> AttributedType,
> AttributedLocInfo> {
> public:
> - AttributedType::Kind getAttrKind() const {
> + attr::Kind getAttrKind() const {
> return getTypePtr()->getAttrKind();
> }
>
> - bool hasAttrExprOperand() const {
> - return (getAttrKind() >= AttributedType::FirstExprOperandKind &&
> - getAttrKind() <= AttributedType::LastExprOperandKind);
> - }
> -
> - bool hasAttrEnumOperand() const {
> - return (getAttrKind() >= AttributedType::FirstEnumOperandKind &&
> - getAttrKind() <= AttributedType::LastEnumOperandKind);
> - }
> -
> - bool hasAttrOperand() const {
> - return hasAttrExprOperand() || hasAttrEnumOperand();
> - }
> -
> bool isQualifier() const {
> return getTypePtr()->isQualifier();
> }
> @@ -897,51 +875,16 @@ public:
> return getInnerTypeLoc();
> }
>
> - /// The location of the attribute name, i.e.
> - /// __attribute__((regparm(1000)))
> - /// ^~~~~~~
> - SourceLocation getAttrNameLoc() const {
> - return getLocalData()->AttrLoc;
> - }
> - void setAttrNameLoc(SourceLocation loc) {
> - getLocalData()->AttrLoc = loc;
> - }
> -
> - /// The attribute's expression operand, if it has one.
> - /// void *cur_thread __attribute__((address_space(21)))
> - /// ^~
> - Expr *getAttrExprOperand() const {
> - assert(hasAttrExprOperand());
> - return getLocalData()->ExprOperand;
> - }
> - void setAttrExprOperand(Expr *e) {
> - assert(hasAttrExprOperand());
> - getLocalData()->ExprOperand = e;
> - }
> -
> - /// The location of the attribute's enumerated operand, if it has one.
> - /// void * __attribute__((objc_gc(weak)))
> - /// ^~~~
> - SourceLocation getAttrEnumOperandLoc() const {
> - assert(hasAttrEnumOperand());
> - return SourceLocation::getFromRawEncoding(getLocalData()->EnumOperandLoc);
> - }
> - void setAttrEnumOperandLoc(SourceLocation loc) {
> - assert(hasAttrEnumOperand());
> - getLocalData()->EnumOperandLoc = loc.getRawEncoding();
> - }
> -
> - /// The location of the parentheses around the operand, if there is
> - /// an operand.
> - /// void * __attribute__((objc_gc(weak)))
> - /// ^ ^
> - SourceRange getAttrOperandParensRange() const {
> - assert(hasAttrOperand());
> - return getLocalData()->OperandParens;
> - }
> - void setAttrOperandParensRange(SourceRange range) {
> - assert(hasAttrOperand());
> - getLocalData()->OperandParens = range;
> + /// The type attribute.
> + const Attr *getAttr() const {
> + return getLocalData()->TypeAttr;
> + }
> + void setAttr(const Attr *A) {
> + getLocalData()->TypeAttr = A;
> + }
> +
> + template<typename T> const T *getAttrAs() {
> + return dyn_cast_or_null<T>(getAttr());
> }
>
> SourceRange getLocalSourceRange() const {
> @@ -954,21 +897,11 @@ public:
> // ^~ ~~
> // That enclosure doesn't necessarily belong to a single attribute
> // anyway.
> - SourceRange range(getAttrNameLoc());
> - if (hasAttrOperand())
> - range.setEnd(getAttrOperandParensRange().getEnd());
> - return range;
> + return getAttr() ? getAttr()->getRange() : SourceRange();
> }
>
> void initializeLocal(ASTContext &Context, SourceLocation loc) {
> - setAttrNameLoc(loc);
> - if (hasAttrExprOperand()) {
> - setAttrOperandParensRange(SourceRange(loc));
> - setAttrExprOperand(nullptr);
> - } else if (hasAttrEnumOperand()) {
> - setAttrOperandParensRange(SourceRange(loc));
> - setAttrEnumOperandLoc(loc);
> - }
> + setAttr(nullptr);
> }
>
> QualType getInnerType() const {
>
> Modified: cfe/trunk/include/clang/Basic/Attr.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=340215&r1=340214&r2=340215&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/Attr.td (original)
> +++ cfe/trunk/include/clang/Basic/Attr.td Mon Aug 20 14:47:29 2018
> @@ -494,10 +494,7 @@ class Attr {
> }
>
> /// A type attribute is not processed on a declaration or a statement.
> -class TypeAttr : Attr {
> - // By default, type attributes do not get an AST node.
> - let ASTNode = 0;
> -}
> +class TypeAttr : Attr;
>
> /// A stmt attribute is not processed on a declaration or a type.
> class StmtAttr : Attr;
> @@ -567,6 +564,8 @@ def AddressSpace : TypeAttr {
> let Spellings = [Clang<"address_space">];
> let Args = [IntArgument<"AddressSpace">];
> let Documentation = [Undocumented];
> + // Represented as a qualifier or DependentAddressSpaceType instead.
> + let ASTNode = 0;
> }
>
> def Alias : Attr {
> @@ -1224,7 +1223,7 @@ def LayoutVersion : InheritableAttr, Tar
> let Documentation = [LayoutVersionDocs];
> }
>
> -def LifetimeBound : InheritableAttr {
> +def LifetimeBound : DeclOrTypeAttr {
> let Spellings = [Clang<"lifetimebound", 0>];
> let Subjects = SubjectList<[ParmVar, ImplicitObjectParameter], ErrorDiag>;
> let Documentation = [LifetimeBoundDocs];
> @@ -1327,12 +1326,16 @@ def NeonPolyVectorType : TypeAttr {
> let Spellings = [Clang<"neon_polyvector_type">];
> let Args = [IntArgument<"NumElements">];
> let Documentation = [Undocumented];
> + // Represented as VectorType instead.
> + let ASTNode = 0;
> }
>
> def NeonVectorType : TypeAttr {
> let Spellings = [Clang<"neon_vector_type">];
> let Args = [IntArgument<"NumElements">];
> let Documentation = [Undocumented];
> + // Represented as VectorType instead.
> + let ASTNode = 0;
> }
>
> def ReturnsTwice : InheritableAttr {
> @@ -1507,6 +1510,14 @@ def TypeNullUnspecified : TypeAttr {
> let Documentation = [TypeNullUnspecifiedDocs];
> }
>
> +// This is a marker used to indicate that an __unsafe_unretained qualifier was
> +// ignored because ARC is not enabled. The usual representation for this
> +// qualifier is as an ObjCOwnership attribute with Kind == "none".
> +def ObjCInertUnsafeUnretained : TypeAttr {
> + let Spellings = [Keyword<"__unsafe_unretained">];
> + let Documentation = [Undocumented];
> +}
> +
> def ObjCKindOf : TypeAttr {
> let Spellings = [Keyword<"__kindof">];
> let Documentation = [Undocumented];
> @@ -1594,7 +1605,7 @@ def ObjCBridgeRelated : InheritableAttr
> let Documentation = [Undocumented];
> }
>
> -def NSReturnsRetained : InheritableAttr {
> +def NSReturnsRetained : DeclOrTypeAttr {
> let Spellings = [Clang<"ns_returns_retained">];
> // let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>;
> let Documentation = [Undocumented];
> @@ -1779,6 +1790,8 @@ def Regparm : TypeAttr {
> let Spellings = [GCC<"regparm">];
> let Args = [UnsignedArgument<"NumParams">];
> let Documentation = [RegparmDocs];
> + // Represented as part of the enclosing function type.
> + let ASTNode = 0;
> }
>
> def ReqdWorkGroupSize : InheritableAttr {
> @@ -2067,10 +2080,9 @@ def ObjCGC : TypeAttr {
> let Documentation = [Undocumented];
> }
>
> -def ObjCOwnership : InheritableAttr {
> +def ObjCOwnership : DeclOrTypeAttr {
> let Spellings = [Clang<"objc_ownership">];
> let Args = [IdentifierArgument<"Kind">];
> - let ASTNode = 0;
> let Documentation = [Undocumented];
> }
>
> @@ -2108,6 +2120,8 @@ def VectorSize : TypeAttr {
> let Spellings = [GCC<"vector_size">];
> let Args = [ExprArgument<"NumBytes">];
> let Documentation = [Undocumented];
> + // Represented as VectorType instead.
> + let ASTNode = 0;
> }
>
> def VecTypeHint : InheritableAttr {
> @@ -2202,7 +2216,7 @@ def AnyX86NoCallerSavedRegisters : Inher
> let Documentation = [AnyX86NoCallerSavedRegistersDocs];
> }
>
> -def AnyX86NoCfCheck : InheritableAttr, TargetSpecificAttr<TargetAnyX86>{
> +def AnyX86NoCfCheck : DeclOrTypeAttr, TargetSpecificAttr<TargetAnyX86>{
> let Spellings = [GCC<"nocf_check">];
> let Subjects = SubjectList<[FunctionLike]>;
> let Documentation = [AnyX86NoCfCheckDocs];
>
> Modified: cfe/trunk/include/clang/Sema/Sema.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=340215&r1=340214&r2=340215&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Sema/Sema.h (original)
> +++ cfe/trunk/include/clang/Sema/Sema.h Mon Aug 20 14:47:29 2018
> @@ -1435,8 +1435,6 @@ public:
>
> TypeSourceInfo *GetTypeForDeclarator(Declarator &D, Scope *S);
> TypeSourceInfo *GetTypeForDeclaratorCast(Declarator &D, QualType FromTy);
> - TypeSourceInfo *GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
> - TypeSourceInfo *ReturnTypeInfo);
>
> /// Package the given type and TSI into a ParsedType.
> ParsedType CreateParsedType(QualType T, TypeSourceInfo *TInfo);
> @@ -3378,30 +3376,6 @@ public:
> /// Valid types should not have multiple attributes with different CCs.
> const AttributedType *getCallingConvAttributedType(QualType T) const;
>
> - /// Check whether a nullability type specifier can be added to the given
> - /// type.
> - ///
> - /// \param type The type to which the nullability specifier will be
> - /// added. On success, this type will be updated appropriately.
> - ///
> - /// \param nullability The nullability specifier to add.
> - ///
> - /// \param nullabilityLoc The location of the nullability specifier.
> - ///
> - /// \param isContextSensitive Whether this nullability specifier was
> - /// written as a context-sensitive keyword (in an Objective-C
> - /// method) or an Objective-C property attribute, rather than as an
> - /// underscored type specifier.
> - ///
> - /// \param allowArrayTypes Whether to accept nullability specifiers on an
> - /// array type (e.g., because it will decay to a pointer).
> - ///
> - /// \returns true if nullability cannot be applied, false otherwise.
> - bool checkNullabilityTypeSpecifier(QualType &type, NullabilityKind nullability,
> - SourceLocation nullabilityLoc,
> - bool isContextSensitive,
> - bool allowArrayTypes);
> -
> /// Stmt attributes - this routine is the top level dispatcher.
> StmtResult ProcessStmtAttributes(Stmt *Stmt,
> const ParsedAttributesView &Attrs,
> @@ -8071,10 +8045,6 @@ public:
> SourceLocation ProtocolRAngleLoc,
> bool FailOnError = false);
>
> - /// Check the application of the Objective-C '__kindof' qualifier to
> - /// the given type.
> - bool checkObjCKindOfType(QualType &type, SourceLocation loc);
> -
> /// Ensure attributes are consistent with type.
> /// \param [in, out] Attributes The attributes to check; they will
> /// be modified to be consistent with \p PropertyTy.
>
> Modified: cfe/trunk/include/clang/Serialization/ASTReader.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTReader.h?rev=340215&r1=340214&r2=340215&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Serialization/ASTReader.h (original)
> +++ cfe/trunk/include/clang/Serialization/ASTReader.h Mon Aug 20 14:47:29 2018
> @@ -2245,6 +2245,9 @@ public:
> CXXTemporary *ReadCXXTemporary(ModuleFile &F, const RecordData &Record,
> unsigned &Idx);
>
> + /// Reads one attribute from the current stream position.
> + Attr *ReadAttr(ModuleFile &M, const RecordData &Record, unsigned &Idx);
> +
> /// Reads attributes from the current stream position.
> void ReadAttributes(ASTRecordReader &Record, AttrVec &Attrs);
>
> @@ -2630,6 +2633,11 @@ public:
> return ASTReader::ReadVersionTuple(Record, Idx);
> }
>
> + /// Reads one attribute from the current stream position, advancing Idx.
> + Attr *readAttr() {
> + return Reader->ReadAttr(*F, Record, Idx);
> + }
> +
> /// Reads attributes from the current stream position, advancing Idx.
> void readAttributes(AttrVec &Attrs) {
> return Reader->ReadAttributes(*this, Attrs);
>
> Modified: cfe/trunk/include/clang/Serialization/ASTWriter.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTWriter.h?rev=340215&r1=340214&r2=340215&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Serialization/ASTWriter.h (original)
> +++ cfe/trunk/include/clang/Serialization/ASTWriter.h Mon Aug 20 14:47:29 2018
> @@ -955,6 +955,9 @@ public:
> return Writer->AddVersionTuple(Version, *Record);
> }
>
> + // Emit an attribute.
> + void AddAttr(const Attr *A);
> +
> /// Emit a list of attributes.
> void AddAttributes(ArrayRef<const Attr*> Attrs);
> };
>
> Modified: cfe/trunk/lib/ARCMigrate/TransGCAttrs.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/TransGCAttrs.cpp?rev=340215&r1=340214&r2=340215&view=diff
> ==============================================================================
> --- cfe/trunk/lib/ARCMigrate/TransGCAttrs.cpp (original)
> +++ cfe/trunk/lib/ARCMigrate/TransGCAttrs.cpp Mon Aug 20 14:47:29 2018
> @@ -81,10 +81,11 @@ public:
> }
>
> bool handleAttr(AttributedTypeLoc TL, Decl *D = nullptr) {
> - if (TL.getAttrKind() != AttributedType::attr_objc_ownership)
> + auto *OwnershipAttr = TL.getAttrAs<ObjCOwnershipAttr>();
> + if (!OwnershipAttr)
> return false;
>
> - SourceLocation Loc = TL.getAttrNameLoc();
> + SourceLocation Loc = OwnershipAttr->getLocation();
> unsigned RawLoc = Loc.getRawEncoding();
> if (MigrateCtx.AttrSet.count(RawLoc))
> return true;
> @@ -93,13 +94,7 @@ public:
> SourceManager &SM = Ctx.getSourceManager();
> if (Loc.isMacroID())
> Loc = SM.getImmediateExpansionRange(Loc).getBegin();
> - SmallString<32> Buf;
> - bool Invalid = false;
> - StringRef Spell = Lexer::getSpelling(
> - SM.getSpellingLoc(TL.getAttrEnumOperandLoc()),
> - Buf, SM, Ctx.getLangOpts(), &Invalid);
> - if (Invalid)
> - return false;
> + StringRef Spell = OwnershipAttr->getKind()->getName();
> MigrationContext::GCAttrOccurrence::AttrKind Kind;
> if (Spell == "strong")
> Kind = MigrationContext::GCAttrOccurrence::Strong;
> @@ -284,7 +279,7 @@ static void checkAllAtProps(MigrationCon
> }
>
> for (unsigned i = 0, e = ATLs.size(); i != e; ++i) {
> - SourceLocation Loc = ATLs[i].first.getAttrNameLoc();
> + SourceLocation Loc = ATLs[i].first.getAttr()->getLocation();
> if (Loc.isMacroID())
> Loc = MigrateCtx.Pass.Ctx.getSourceManager()
> .getImmediateExpansionRange(Loc)
>
> Modified: cfe/trunk/lib/ARCMigrate/Transforms.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/Transforms.cpp?rev=340215&r1=340214&r2=340215&view=diff
> ==============================================================================
> --- cfe/trunk/lib/ARCMigrate/Transforms.cpp (original)
> +++ cfe/trunk/lib/ARCMigrate/Transforms.cpp Mon Aug 20 14:47:29 2018
> @@ -359,7 +359,7 @@ MigrationContext::~MigrationContext() {
> bool MigrationContext::isGCOwnedNonObjC(QualType T) {
> while (!T.isNull()) {
> if (const AttributedType *AttrT = T->getAs<AttributedType>()) {
> - if (AttrT->getAttrKind() == AttributedType::attr_objc_ownership)
> + if (AttrT->getAttrKind() == attr::ObjCOwnership)
> return !AttrT->getModifiedType()->isObjCRetainableType();
> }
>
>
> Modified: cfe/trunk/lib/AST/ASTContext.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=340215&r1=340214&r2=340215&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/ASTContext.cpp (original)
> +++ cfe/trunk/lib/AST/ASTContext.cpp Mon Aug 20 14:47:29 2018
> @@ -3876,7 +3876,7 @@ QualType ASTContext::getEnumType(const E
> return QualType(newType, 0);
> }
>
> -QualType ASTContext::getAttributedType(AttributedType::Kind attrKind,
> +QualType ASTContext::getAttributedType(attr::Kind attrKind,
> QualType modifiedType,
> QualType equivalentType) {
> llvm::FoldingSetNodeID id;
>
> Modified: cfe/trunk/lib/AST/Type.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=340215&r1=340214&r2=340215&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/Type.cpp (original)
> +++ cfe/trunk/lib/AST/Type.cpp Mon Aug 20 14:47:29 2018
> @@ -592,28 +592,6 @@ bool Type::isObjCClassOrClassKindOfType(
> return OPT->isObjCClassType() || OPT->isObjCQualifiedClassType();
> }
>
> -/// Was this type written with the special inert-in-MRC __unsafe_unretained
> -/// qualifier?
> -///
> -/// This approximates the answer to the following question: if this
> -/// translation unit were compiled in ARC, would this type be qualified
> -/// with __unsafe_unretained?
> -bool Type::isObjCInertUnsafeUnretainedType() const {
> - const Type *cur = this;
> - while (true) {
> - if (const auto attributed = dyn_cast<AttributedType>(cur)) {
> - if (attributed->getAttrKind() ==
> - AttributedType::attr_objc_inert_unsafe_unretained)
> - return true;
> - }
> -
> - // Single-step desugar until we run out of sugar.
> - QualType next = cur->getLocallyUnqualifiedSingleStepDesugaredType();
> - if (next.getTypePtr() == cur) return false;
> - cur = next.getTypePtr();
> - }
> -}
> -
> ObjCTypeParamType::ObjCTypeParamType(const ObjCTypeParamDecl *D,
> QualType can,
> ArrayRef<ObjCProtocolDecl *> protocols)
> @@ -1641,6 +1619,16 @@ TagDecl *Type::getAsTagDecl() const {
> return nullptr;
> }
>
> +bool Type::hasAttr(attr::Kind AK) const {
> + const Type *Cur = this;
> + while (const auto *AT = Cur->getAs<AttributedType>()) {
> + if (AT->getAttrKind() == AK)
> + return true;
> + Cur = AT->getEquivalentType().getTypePtr();
> + }
> + return false;
> +}
> +
> namespace {
>
> class GetContainedDeducedTypeVisitor :
> @@ -3168,105 +3156,58 @@ bool RecordType::hasConstFields() const
> }
>
> bool AttributedType::isQualifier() const {
> + // FIXME: Generate this with TableGen.
> switch (getAttrKind()) {
> // These are type qualifiers in the traditional C sense: they annotate
> // something about a specific value/variable of a type. (They aren't
> // always part of the canonical type, though.)
> - case AttributedType::attr_address_space:
> - case AttributedType::attr_objc_gc:
> - case AttributedType::attr_objc_ownership:
> - case AttributedType::attr_objc_inert_unsafe_unretained:
> - case AttributedType::attr_nonnull:
> - case AttributedType::attr_nullable:
> - case AttributedType::attr_null_unspecified:
> - case AttributedType::attr_lifetimebound:
> - return true;
> -
> - // These aren't qualifiers; they rewrite the modified type to be a
> - // semantically different type.
> - case AttributedType::attr_regparm:
> - case AttributedType::attr_vector_size:
> - case AttributedType::attr_neon_vector_type:
> - case AttributedType::attr_neon_polyvector_type:
> - case AttributedType::attr_pcs:
> - case AttributedType::attr_pcs_vfp:
> - case AttributedType::attr_noreturn:
> - case AttributedType::attr_cdecl:
> - case AttributedType::attr_fastcall:
> - case AttributedType::attr_stdcall:
> - case AttributedType::attr_thiscall:
> - case AttributedType::attr_regcall:
> - case AttributedType::attr_pascal:
> - case AttributedType::attr_swiftcall:
> - case AttributedType::attr_vectorcall:
> - case AttributedType::attr_inteloclbicc:
> - case AttributedType::attr_preserve_most:
> - case AttributedType::attr_preserve_all:
> - case AttributedType::attr_ms_abi:
> - case AttributedType::attr_sysv_abi:
> - case AttributedType::attr_ptr32:
> - case AttributedType::attr_ptr64:
> - case AttributedType::attr_sptr:
> - case AttributedType::attr_uptr:
> - case AttributedType::attr_objc_kindof:
> - case AttributedType::attr_ns_returns_retained:
> - case AttributedType::attr_nocf_check:
> + case attr::ObjCGC:
> + case attr::ObjCOwnership:
> + case attr::ObjCInertUnsafeUnretained:
> + case attr::TypeNonNull:
> + case attr::TypeNullable:
> + case attr::TypeNullUnspecified:
> + case attr::LifetimeBound:
> + return true;
> +
> + // All other type attributes aren't qualifiers; they rewrite the modified
> + // type to be a semantically different type.
> + default:
> return false;
> }
> - llvm_unreachable("bad attributed type kind");
> }
>
> bool AttributedType::isMSTypeSpec() const {
> + // FIXME: Generate this with TableGen?
> switch (getAttrKind()) {
> - default: return false;
> - case attr_ptr32:
> - case attr_ptr64:
> - case attr_sptr:
> - case attr_uptr:
> + default: return false;
> + case attr::Ptr32:
> + case attr::Ptr64:
> + case attr::SPtr:
> + case attr::UPtr:
> return true;
> }
> llvm_unreachable("invalid attr kind");
> }
>
> bool AttributedType::isCallingConv() const {
> + // FIXME: Generate this with TableGen.
> switch (getAttrKind()) {
> - case attr_ptr32:
> - case attr_ptr64:
> - case attr_sptr:
> - case attr_uptr:
> - case attr_address_space:
> - case attr_regparm:
> - case attr_vector_size:
> - case attr_neon_vector_type:
> - case attr_neon_polyvector_type:
> - case attr_objc_gc:
> - case attr_objc_ownership:
> - case attr_objc_inert_unsafe_unretained:
> - case attr_noreturn:
> - case attr_nonnull:
> - case attr_ns_returns_retained:
> - case attr_nullable:
> - case attr_null_unspecified:
> - case attr_objc_kindof:
> - case attr_nocf_check:
> - case attr_lifetimebound:
> - return false;
> -
> - case attr_pcs:
> - case attr_pcs_vfp:
> - case attr_cdecl:
> - case attr_fastcall:
> - case attr_stdcall:
> - case attr_thiscall:
> - case attr_regcall:
> - case attr_swiftcall:
> - case attr_vectorcall:
> - case attr_pascal:
> - case attr_ms_abi:
> - case attr_sysv_abi:
> - case attr_inteloclbicc:
> - case attr_preserve_most:
> - case attr_preserve_all:
> + default: return false;
> + case attr::Pcs:
> + case attr::CDecl:
> + case attr::FastCall:
> + case attr::StdCall:
> + case attr::ThisCall:
> + case attr::RegCall:
> + case attr::SwiftCall:
> + case attr::VectorCall:
> + case attr::Pascal:
> + case attr::MSABI:
> + case attr::SysVABI:
> + case attr::IntelOclBicc:
> + case attr::PreserveMost:
> + case attr::PreserveAll:
> return true;
> }
> llvm_unreachable("invalid attr kind");
> @@ -3712,23 +3653,18 @@ LinkageInfo Type::getLinkageAndVisibilit
> return LinkageComputer{}.getTypeLinkageAndVisibility(this);
> }
>
> -Optional<NullabilityKind> Type::getNullability(const ASTContext &context) const {
> - QualType type(this, 0);
> - do {
> +Optional<NullabilityKind>
> +Type::getNullability(const ASTContext &Context) const {
> + QualType Type(this, 0);
> + while (const auto *AT = Type->getAs<AttributedType>()) {
> // Check whether this is an attributed type with nullability
> // information.
> - if (auto attributed = dyn_cast<AttributedType>(type.getTypePtr())) {
> - if (auto nullability = attributed->getImmediateNullability())
> - return nullability;
> - }
> -
> - // Desugar the type. If desugaring does nothing, we're done.
> - QualType desugared = type.getSingleStepDesugaredType(context);
> - if (desugared.getTypePtr() == type.getTypePtr())
> - return None;
> + if (auto Nullability = AT->getImmediateNullability())
> + return Nullability;
>
> - type = desugared;
> - } while (true);
> + Type = AT->getEquivalentType();
> + }
> + return None;
> }
>
> bool Type::canHaveNullability(bool ResultIfUnknown) const {
> @@ -3841,12 +3777,13 @@ bool Type::canHaveNullability(bool Resul
> llvm_unreachable("bad type kind!");
> }
>
> -llvm::Optional<NullabilityKind> AttributedType::getImmediateNullability() const {
> - if (getAttrKind() == AttributedType::attr_nonnull)
> +llvm::Optional<NullabilityKind>
> +AttributedType::getImmediateNullability() const {
> + if (getAttrKind() == attr::TypeNonNull)
> return NullabilityKind::NonNull;
> - if (getAttrKind() == AttributedType::attr_nullable)
> + if (getAttrKind() == attr::TypeNullable)
> return NullabilityKind::Nullable;
> - if (getAttrKind() == AttributedType::attr_null_unspecified)
> + if (getAttrKind() == attr::TypeNullUnspecified)
> return NullabilityKind::Unspecified;
> return None;
> }
>
> Modified: cfe/trunk/lib/AST/TypeLoc.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypeLoc.cpp?rev=340215&r1=340214&r2=340215&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/TypeLoc.cpp (original)
> +++ cfe/trunk/lib/AST/TypeLoc.cpp Mon Aug 20 14:47:29 2018
> @@ -404,11 +404,11 @@ TypeLoc TypeLoc::IgnoreParensImpl(TypeLo
> }
>
> SourceLocation TypeLoc::findNullabilityLoc() const {
> - if (auto attributedLoc = getAs<AttributedTypeLoc>()) {
> - if (attributedLoc.getAttrKind() == AttributedType::attr_nullable ||
> - attributedLoc.getAttrKind() == AttributedType::attr_nonnull ||
> - attributedLoc.getAttrKind() == AttributedType::attr_null_unspecified)
> - return attributedLoc.getAttrNameLoc();
> + if (auto ATL = getAs<AttributedTypeLoc>()) {
> + const Attr *A = ATL.getAttr();
> + if (A && (isa<TypeNullableAttr>(A) || isa<TypeNonNullAttr>(A) ||
> + isa<TypeNullUnspecifiedAttr>(A)))
> + return A->getLocation();
> }
>
> return {};
>
> Modified: cfe/trunk/lib/AST/TypePrinter.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypePrinter.cpp?rev=340215&r1=340214&r2=340215&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/TypePrinter.cpp (original)
> +++ cfe/trunk/lib/AST/TypePrinter.cpp Mon Aug 20 14:47:29 2018
> @@ -1354,12 +1354,14 @@ void TypePrinter::printPackExpansionAfte
>
> void TypePrinter::printAttributedBefore(const AttributedType *T,
> raw_ostream &OS) {
> + // FIXME: Generate this with TableGen.
> +
> // Prefer the macro forms of the GC and ownership qualifiers.
> - if (T->getAttrKind() == AttributedType::attr_objc_gc ||
> - T->getAttrKind() == AttributedType::attr_objc_ownership)
> + if (T->getAttrKind() == attr::ObjCGC ||
> + T->getAttrKind() == attr::ObjCOwnership)
> return printBefore(T->getEquivalentType(), OS);
>
> - if (T->getAttrKind() == AttributedType::attr_objc_kindof)
> + if (T->getAttrKind() == attr::ObjCKindOf)
> OS << "__kindof ";
>
> printBefore(T->getModifiedType(), OS);
> @@ -1367,23 +1369,21 @@ void TypePrinter::printAttributedBefore(
> if (T->isMSTypeSpec()) {
> switch (T->getAttrKind()) {
> default: return;
> - case AttributedType::attr_ptr32: OS << " __ptr32"; break;
> - case AttributedType::attr_ptr64: OS << " __ptr64"; break;
> - case AttributedType::attr_sptr: OS << " __sptr"; break;
> - case AttributedType::attr_uptr: OS << " __uptr"; break;
> + case attr::Ptr32: OS << " __ptr32"; break;
> + case attr::Ptr64: OS << " __ptr64"; break;
> + case attr::SPtr: OS << " __sptr"; break;
> + case attr::UPtr: OS << " __uptr"; break;
> }
> spaceBeforePlaceHolder(OS);
> }
>
> // Print nullability type specifiers.
> - if (T->getAttrKind() == AttributedType::attr_nonnull ||
> - T->getAttrKind() == AttributedType::attr_nullable ||
> - T->getAttrKind() == AttributedType::attr_null_unspecified) {
> - if (T->getAttrKind() == AttributedType::attr_nonnull)
> + if (T->getImmediateNullability()) {
> + if (T->getAttrKind() == attr::TypeNonNull)
> OS << " _Nonnull";
> - else if (T->getAttrKind() == AttributedType::attr_nullable)
> + else if (T->getAttrKind() == attr::TypeNullable)
> OS << " _Nullable";
> - else if (T->getAttrKind() == AttributedType::attr_null_unspecified)
> + else if (T->getAttrKind() == attr::TypeNullUnspecified)
> OS << " _Null_unspecified";
> else
> llvm_unreachable("unhandled nullability");
> @@ -1393,9 +1393,11 @@ void TypePrinter::printAttributedBefore(
>
> void TypePrinter::printAttributedAfter(const AttributedType *T,
> raw_ostream &OS) {
> + // FIXME: Generate this with TableGen.
> +
> // Prefer the macro forms of the GC and ownership qualifiers.
> - if (T->getAttrKind() == AttributedType::attr_objc_gc ||
> - T->getAttrKind() == AttributedType::attr_objc_ownership)
> + if (T->getAttrKind() == attr::ObjCGC ||
> + T->getAttrKind() == attr::ObjCOwnership)
> return printAfter(T->getEquivalentType(), OS);
>
> // If this is a calling convention attribute, don't print the implicit CC from
> @@ -1406,107 +1408,74 @@ void TypePrinter::printAttributedAfter(c
>
> // Some attributes are printed as qualifiers before the type, so we have
> // nothing left to do.
> - if (T->getAttrKind() == AttributedType::attr_objc_kindof ||
> - T->isMSTypeSpec() ||
> - T->getAttrKind() == AttributedType::attr_nonnull ||
> - T->getAttrKind() == AttributedType::attr_nullable ||
> - T->getAttrKind() == AttributedType::attr_null_unspecified)
> + if (T->getAttrKind() == attr::ObjCKindOf ||
> + T->isMSTypeSpec() || T->getImmediateNullability())
> return;
>
> // Don't print the inert __unsafe_unretained attribute at all.
> - if (T->getAttrKind() == AttributedType::attr_objc_inert_unsafe_unretained)
> + if (T->getAttrKind() == attr::ObjCInertUnsafeUnretained)
> return;
>
> // Don't print ns_returns_retained unless it had an effect.
> - if (T->getAttrKind() == AttributedType::attr_ns_returns_retained &&
> + if (T->getAttrKind() == attr::NSReturnsRetained &&
> !T->getEquivalentType()->castAs<FunctionType>()
> ->getExtInfo().getProducesResult())
> return;
>
> - if (T->getAttrKind() == AttributedType::attr_lifetimebound) {
> + if (T->getAttrKind() == attr::LifetimeBound) {
> OS << " [[clang::lifetimebound]]";
> return;
> }
>
> OS << " __attribute__((";
> switch (T->getAttrKind()) {
> - case AttributedType::attr_lifetimebound:
> - case AttributedType::attr_nonnull:
> - case AttributedType::attr_nullable:
> - case AttributedType::attr_null_unspecified:
> - case AttributedType::attr_objc_gc:
> - case AttributedType::attr_objc_inert_unsafe_unretained:
> - case AttributedType::attr_objc_kindof:
> - case AttributedType::attr_objc_ownership:
> - case AttributedType::attr_ptr32:
> - case AttributedType::attr_ptr64:
> - case AttributedType::attr_sptr:
> - case AttributedType::attr_uptr:
> +#define TYPE_ATTR(NAME)
> +#define DECL_OR_TYPE_ATTR(NAME)
> +#define ATTR(NAME) case attr::NAME:
> +#include "clang/Basic/AttrList.inc"
> + llvm_unreachable("non-type attribute attached to type");
> +
> + case attr::OpenCLPrivateAddressSpace:
> + case attr::OpenCLGlobalAddressSpace:
> + case attr::OpenCLLocalAddressSpace:
> + case attr::OpenCLConstantAddressSpace:
> + case attr::OpenCLGenericAddressSpace:
> + // FIXME: Update printAttributedBefore to print these once we generate
> + // AttributedType nodes for them.
> + break;
> +
> + case attr::LifetimeBound:
> + case attr::TypeNonNull:
> + case attr::TypeNullable:
> + case attr::TypeNullUnspecified:
> + case attr::ObjCGC:
> + case attr::ObjCInertUnsafeUnretained:
> + case attr::ObjCKindOf:
> + case attr::ObjCOwnership:
> + case attr::Ptr32:
> + case attr::Ptr64:
> + case attr::SPtr:
> + case attr::UPtr:
> llvm_unreachable("This attribute should have been handled already");
>
> - case AttributedType::attr_address_space:
> - OS << "address_space(";
> - // FIXME: printing the raw LangAS value is wrong. This should probably
> - // use the same code as Qualifiers::print()
> - OS << (unsigned)T->getEquivalentType().getAddressSpace();
> - OS << ')';
> - break;
> -
> - case AttributedType::attr_vector_size:
> - OS << "__vector_size__(";
> - if (const auto *vector = T->getEquivalentType()->getAs<VectorType>()) {
> - OS << vector->getNumElements();
> - OS << " * sizeof(";
> - print(vector->getElementType(), OS, StringRef());
> - OS << ')';
> - }
> - OS << ')';
> - break;
> -
> - case AttributedType::attr_neon_vector_type:
> - case AttributedType::attr_neon_polyvector_type: {
> - if (T->getAttrKind() == AttributedType::attr_neon_vector_type)
> - OS << "neon_vector_type(";
> - else
> - OS << "neon_polyvector_type(";
> - const auto *vector = T->getEquivalentType()->getAs<VectorType>();
> - OS << vector->getNumElements();
> - OS << ')';
> - break;
> - }
> -
> - case AttributedType::attr_regparm: {
> - // FIXME: When Sema learns to form this AttributedType, avoid printing the
> - // attribute again in printFunctionProtoAfter.
> - OS << "regparm(";
> - QualType t = T->getEquivalentType();
> - while (!t->isFunctionType())
> - t = t->getPointeeType();
> - OS << t->getAs<FunctionType>()->getRegParmType();
> - OS << ')';
> - break;
> - }
> -
> - case AttributedType::attr_ns_returns_retained:
> + case attr::NSReturnsRetained:
> OS << "ns_returns_retained";
> break;
>
> // FIXME: When Sema learns to form this AttributedType, avoid printing the
> // attribute again in printFunctionProtoAfter.
> - case AttributedType::attr_noreturn: OS << "noreturn"; break;
> - case AttributedType::attr_nocf_check: OS << "nocf_check"; break;
> - case AttributedType::attr_cdecl: OS << "cdecl"; break;
> - case AttributedType::attr_fastcall: OS << "fastcall"; break;
> - case AttributedType::attr_stdcall: OS << "stdcall"; break;
> - case AttributedType::attr_thiscall: OS << "thiscall"; break;
> - case AttributedType::attr_swiftcall: OS << "swiftcall"; break;
> - case AttributedType::attr_vectorcall: OS << "vectorcall"; break;
> - case AttributedType::attr_pascal: OS << "pascal"; break;
> - case AttributedType::attr_ms_abi: OS << "ms_abi"; break;
> - case AttributedType::attr_sysv_abi: OS << "sysv_abi"; break;
> - case AttributedType::attr_regcall: OS << "regcall"; break;
> - case AttributedType::attr_pcs:
> - case AttributedType::attr_pcs_vfp: {
> + case attr::AnyX86NoCfCheck: OS << "nocf_check"; break;
> + case attr::CDecl: OS << "cdecl"; break;
> + case attr::FastCall: OS << "fastcall"; break;
> + case attr::StdCall: OS << "stdcall"; break;
> + case attr::ThisCall: OS << "thiscall"; break;
> + case attr::SwiftCall: OS << "swiftcall"; break;
> + case attr::VectorCall: OS << "vectorcall"; break;
> + case attr::Pascal: OS << "pascal"; break;
> + case attr::MSABI: OS << "ms_abi"; break;
> + case attr::SysVABI: OS << "sysv_abi"; break;
> + case attr::RegCall: OS << "regcall"; break;
> + case attr::Pcs: {
> OS << "pcs(";
> QualType t = T->getEquivalentType();
> while (!t->isFunctionType())
> @@ -1517,12 +1486,12 @@ void TypePrinter::printAttributedAfter(c
> break;
> }
>
> - case AttributedType::attr_inteloclbicc: OS << "inteloclbicc"; break;
> - case AttributedType::attr_preserve_most:
> + case attr::IntelOclBicc: OS << "inteloclbicc"; break;
> + case attr::PreserveMost:
> OS << "preserve_most";
> break;
>
> - case AttributedType::attr_preserve_all:
> + case attr::PreserveAll:
> OS << "preserve_all";
> break;
> }
>
> Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=340215&r1=340214&r2=340215&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Aug 20 14:47:29 2018
> @@ -5999,14 +5999,14 @@ static void checkAttributesAfterMerging(
> // 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 (ATL.getAttrKind() == AttributedType::attr_lifetimebound) {
> + if (const auto *A = ATL.getAttrAs<LifetimeBoundAttr>()) {
> const auto *MD = dyn_cast<CXXMethodDecl>(FD);
> if (!MD || MD->isStatic()) {
> - S.Diag(ATL.getAttrNameLoc(), diag::err_lifetimebound_no_object_param)
> - << !MD << ATL.getLocalSourceRange();
> + S.Diag(A->getLocation(), diag::err_lifetimebound_no_object_param)
> + << !MD << A->getRange();
> } else if (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)) {
> - S.Diag(ATL.getAttrNameLoc(), diag::err_lifetimebound_ctor_dtor)
> - << isa<CXXDestructorDecl>(MD) << ATL.getLocalSourceRange();
> + S.Diag(A->getLocation(), diag::err_lifetimebound_ctor_dtor)
> + << isa<CXXDestructorDecl>(MD) << A->getRange();
> }
> }
> }
>
> Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=340215&r1=340214&r2=340215&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Aug 20 14:47:29 2018
> @@ -14648,15 +14648,15 @@ static bool captureInBlock(BlockScopeInf
> // 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_objc_ownership in Ty. The existence of AttributedType of kind
> - // attr_objc_ownership implies __autoreleasing was explicitly specified
> + // attr::ObjCOwnership in Ty. The existence of AttributedType of kind
> + // attr::ObjCOwnership 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() == AttributedType::attr_objc_ownership)
> + if (AttrTy->getAttrKind() == attr::ObjCOwnership)
> return true;
>
> - // Peel off AttributedTypes that are not of kind objc_ownership.
> + // Peel off AttributedTypes that are not of kind ObjCOwnership.
> Ty = AttrTy->getModifiedType();
> }
>
>
> Modified: cfe/trunk/lib/Sema/SemaInit.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=340215&r1=340214&r2=340215&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaInit.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaInit.cpp Mon Aug 20 14:47:29 2018
> @@ -6360,7 +6360,7 @@ static bool implicitObjectParamIsLifetim
> for (TypeLoc TL = TSI->getTypeLoc();
> (ATL = TL.getAsAdjusted<AttributedTypeLoc>());
> TL = ATL.getModifiedLoc()) {
> - if (ATL.getAttrKind() == AttributedType::attr_lifetimebound)
> + if (ATL.getAttrAs<LifetimeBoundAttr>())
> return true;
> }
> return false;
>
> Modified: cfe/trunk/lib/Sema/SemaObjCProperty.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaObjCProperty.cpp?rev=340215&r1=340214&r2=340215&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaObjCProperty.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaObjCProperty.cpp Mon Aug 20 14:47:29 2018
> @@ -2384,7 +2384,7 @@ void Sema::ProcessPropertyDecl(ObjCPrope
> QualType modifiedTy = resultTy;
> if (auto nullability = AttributedType::stripOuterNullability(modifiedTy)) {
> if (*nullability == NullabilityKind::Unspecified)
> - resultTy = Context.getAttributedType(AttributedType::attr_nonnull,
> + resultTy = Context.getAttributedType(attr::TypeNonNull,
> modifiedTy, modifiedTy);
> }
> }
> @@ -2458,7 +2458,7 @@ void Sema::ProcessPropertyDecl(ObjCPrope
> QualType modifiedTy = paramTy;
> if (auto nullability = AttributedType::stripOuterNullability(modifiedTy)){
> if (*nullability == NullabilityKind::Unspecified)
> - paramTy = Context.getAttributedType(AttributedType::attr_nullable,
> + paramTy = Context.getAttributedType(attr::TypeNullable,
> modifiedTy, modifiedTy);
> }
> }
>
> Modified: cfe/trunk/lib/Sema/SemaType.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=340215&r1=340214&r2=340215&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaType.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaType.cpp Mon Aug 20 14:47:29 2018
> @@ -172,6 +172,16 @@ 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),
> @@ -230,6 +240,43 @@ 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;
>
> @@ -3832,6 +3879,32 @@ static bool hasOuterPointerLikeChunk(con
> 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) {
> @@ -4184,9 +4257,8 @@ static TypeSourceInfo *GetFullTypeForDec
> pointerKind, D.getDeclSpec().getTypeSpecTypeLoc(),
> D.getDeclSpec().getEndLoc(),
> D.getMutableDeclSpec().getAttributes())) {
> - T = Context.getAttributedType(
> - AttributedType::getNullabilityAttrKind(*inferNullability),T,T);
> - attr->setUsedAsTypeAttr();
> + T = state.getAttributedType(
> + createNullabilityAttr(Context, *attr, *inferNullability), T, T);
> }
> }
> }
> @@ -5025,7 +5097,7 @@ static TypeSourceInfo *GetFullTypeForDec
> if (D.isInvalidType())
> return Context.getTrivialTypeSourceInfo(T);
>
> - return S.GetTypeSourceInfoForDeclarator(D, T, TInfo);
> + return GetTypeSourceInfoForDeclarator(state, T, TInfo);
> }
>
> /// GetTypeForDeclarator - Convert the type for the specified
> @@ -5161,131 +5233,25 @@ TypeSourceInfo *Sema::GetTypeForDeclarat
> 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,
> - 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!");
> + TypeProcessingState &State) {
> + TL.setAttr(State.takeAttrForAttributedType(TL.getTypePtr()));
> }
>
> namespace {
> class TypeSpecLocFiller : public TypeLocVisitor<TypeSpecLocFiller> {
> ASTContext &Context;
> + TypeProcessingState &State;
> const DeclSpec &DS;
>
> public:
> - TypeSpecLocFiller(ASTContext &Context, const DeclSpec &DS)
> - : Context(Context), DS(DS) {}
> + TypeSpecLocFiller(ASTContext &Context, TypeProcessingState &State,
> + const DeclSpec &DS)
> + : Context(Context), State(State), DS(DS) {}
>
> void VisitAttributedTypeLoc(AttributedTypeLoc TL) {
> - fillAttributedTypeLoc(TL, DS.getAttributes(), ParsedAttributesView{});
> Visit(TL.getModifiedLoc());
> + fillAttributedTypeLoc(TL, State);
> }
> void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
> Visit(TL.getUnqualifiedLoc());
> @@ -5442,11 +5408,13 @@ namespace {
>
> class DeclaratorLocFiller : public TypeLocVisitor<DeclaratorLocFiller> {
> ASTContext &Context;
> + TypeProcessingState &State;
> const DeclaratorChunk &Chunk;
>
> public:
> - DeclaratorLocFiller(ASTContext &Context, const DeclaratorChunk &Chunk)
> - : Context(Context), Chunk(Chunk) {}
> + DeclaratorLocFiller(ASTContext &Context, TypeProcessingState &State,
> + const DeclaratorChunk &Chunk)
> + : Context(Context), State(State), Chunk(Chunk) {}
>
> void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
> llvm_unreachable("qualified type locs not expected here!");
> @@ -5456,7 +5424,7 @@ namespace {
> }
>
> void VisitAttributedTypeLoc(AttributedTypeLoc TL) {
> - fillAttributedTypeLoc(TL, Chunk.getAttrs(), ParsedAttributesView{});
> + fillAttributedTypeLoc(TL, State);
> }
> void VisitAdjustedTypeLoc(AdjustedTypeLoc TL) {
> // nothing
> @@ -5613,10 +5581,13 @@ fillDependentAddressSpaceTypeLoc(Depende
> /// 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.
> -TypeSourceInfo *
> -Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
> - TypeSourceInfo *ReturnTypeInfo) {
> - TypeSourceInfo *TInfo = Context.CreateTypeSourceInfo(T);
> +static TypeSourceInfo *
> +GetTypeSourceInfoForDeclarator(TypeProcessingState &State,
> + QualType T, TypeSourceInfo *ReturnTypeInfo) {
> + Sema &S = State.getSema();
> + Declarator &D = State.getDeclarator();
> +
> + TypeSourceInfo *TInfo = S.Context.CreateTypeSourceInfo(T);
> UnqualTypeLoc CurrTL = TInfo->getTypeLoc().getUnqualifiedLoc();
>
> // Handle parameter packs whose type is a pack expansion.
> @@ -5626,7 +5597,6 @@ Sema::GetTypeSourceInfoForDeclarator(Dec
> }
>
> for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
> -
> if (DependentAddressSpaceTypeLoc DASTL =
> CurrTL.getAs<DependentAddressSpaceTypeLoc>()) {
> fillDependentAddressSpaceTypeLoc(DASTL, D.getTypeObject(i).getAttrs());
> @@ -5641,8 +5611,7 @@ Sema::GetTypeSourceInfoForDeclarator(Dec
> }
>
> while (AttributedTypeLoc TL = CurrTL.getAs<AttributedTypeLoc>()) {
> - fillAttributedTypeLoc(TL, D.getTypeObject(i).getAttrs(),
> - D.getAttributes());
> + fillAttributedTypeLoc(TL, State);
> CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
> }
>
> @@ -5650,7 +5619,7 @@ Sema::GetTypeSourceInfoForDeclarator(Dec
> while (AdjustedTypeLoc TL = CurrTL.getAs<AdjustedTypeLoc>())
> CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
>
> - DeclaratorLocFiller(Context, D.getTypeObject(i)).Visit(CurrTL);
> + DeclaratorLocFiller(S.Context, State, D.getTypeObject(i)).Visit(CurrTL);
> CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc();
> }
>
> @@ -5661,7 +5630,7 @@ Sema::GetTypeSourceInfoForDeclarator(Dec
> assert(TL.getFullDataSize() == CurrTL.getFullDataSize());
> memcpy(CurrTL.getOpaqueData(), TL.getOpaqueData(), TL.getFullDataSize());
> } else {
> - TypeSpecLocFiller(Context, D.getDeclSpec()).Visit(CurrTL);
> + TypeSpecLocFiller(S.Context, State, D.getDeclSpec()).Visit(CurrTL);
> }
>
> return TInfo;
> @@ -5890,7 +5859,7 @@ static bool hasDirectOwnershipQualifier(
> while (true) {
> // __strong id
> if (const AttributedType *attr = dyn_cast<AttributedType>(type)) {
> - if (attr->getAttrKind() == AttributedType::attr_objc_ownership)
> + if (attr->getAttrKind() == attr::ObjCOwnership)
> return true;
>
> type = attr->getModifiedType();
> @@ -6034,9 +6003,9 @@ static bool handleObjCOwnershipTypeAttr(
> // the coexistence problems with __unsafe_unretained.
> if (!S.getLangOpts().ObjCAutoRefCount &&
> lifetime == Qualifiers::OCL_ExplicitNone) {
> - type = S.Context.getAttributedType(
> - AttributedType::attr_objc_inert_unsafe_unretained,
> - type, type);
> + type = state.getAttributedType(
> + createSimpleAttr<ObjCInertUnsafeUnretainedAttr>(S.Context, attr),
> + type, type);
> return true;
> }
>
> @@ -6046,9 +6015,12 @@ static bool handleObjCOwnershipTypeAttr(
>
> // If we have a valid source location for the attribute, use an
> // AttributedType instead.
> - if (AttrLoc.isValid())
> - type = S.Context.getAttributedType(AttributedType::attr_objc_ownership,
> - origType, type);
> + if (AttrLoc.isValid()) {
> + type = state.getAttributedType(::new (S.Context) ObjCOwnershipAttr(
> + attr.getRange(), S.Context, II,
> + attr.getAttributeSpellingListIndex()),
> + origType, type);
> + }
>
> auto diagnoseOrDelay = [](Sema &S, SourceLocation loc,
> unsigned diagnostic, QualType type) {
> @@ -6148,8 +6120,10 @@ static bool handleObjCGCTypeAttr(TypePro
>
> // Make an attributed type to preserve the source information.
> if (attr.getLoc().isValid())
> - type = S.Context.getAttributedType(AttributedType::attr_objc_gc,
> - origType, type);
> + type = state.getAttributedType(
> + ::new (S.Context) ObjCGCAttr(attr.getRange(), S.Context, II,
> + attr.getAttributeSpellingListIndex()),
> + origType, type);
>
> return true;
> }
> @@ -6292,37 +6266,50 @@ namespace {
> } // end anonymous namespace
>
> static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State,
> - ParsedAttr &Attr, QualType &Type) {
> + ParsedAttr &PAttr, QualType &Type) {
> Sema &S = State.getSema();
>
> - ParsedAttr::Kind Kind = Attr.getKind();
> + 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();
> QualType Desugared = Type;
> const AttributedType *AT = dyn_cast<AttributedType>(Type);
> while (AT) {
> - AttributedType::Kind CurAttrKind = AT->getAttrKind();
> + attr::Kind CurAttrKind = AT->getAttrKind();
>
> // You cannot specify duplicate type attributes, so if the attribute has
> // already been applied, flag it.
> - if (getAttrListKind(CurAttrKind) == Kind) {
> - S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute_exact)
> - << Attr.getName();
> + if (NewAttrKind == CurAttrKind) {
> + S.Diag(PAttr.getLoc(), diag::warn_duplicate_attribute_exact)
> + << PAttr.getName();
> return true;
> }
>
> // You cannot have both __sptr and __uptr on the same type, nor can you
> // have __ptr32 and __ptr64.
> - 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)
> + if ((CurAttrKind == attr::Ptr32 && NewAttrKind == attr::Ptr64) ||
> + (CurAttrKind == attr::Ptr64 && NewAttrKind == attr::Ptr32)) {
> + S.Diag(PAttr.getLoc(), diag::err_attributes_are_not_compatible)
> << "'__ptr32'" << "'__ptr64'";
> return true;
> - } 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)
> + } else if ((CurAttrKind == attr::SPtr && NewAttrKind == attr::UPtr) ||
> + (CurAttrKind == attr::UPtr && NewAttrKind == attr::SPtr)) {
> + S.Diag(PAttr.getLoc(), diag::err_attributes_are_not_compatible)
> << "'__sptr'" << "'__uptr'";
> return true;
> }
> @@ -6333,41 +6320,64 @@ static bool handleMSPointerTypeQualifier
>
> // 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(Attr.getLoc(), diag::err_attribute_no_member_pointers) << Attr;
> + S.Diag(PAttr.getLoc(), diag::err_attribute_no_member_pointers) << PAttr;
> else
> - S.Diag(Attr.getLoc(), diag::err_attribute_pointers_only) << Attr << 0;
> + S.Diag(PAttr.getLoc(), diag::err_attribute_pointers_only) << PAttr << 0;
> return true;
> }
>
> - 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;
> - }
> -
> - Type = S.Context.getAttributedType(TAK, Type, Type);
> + Type = State.getAttributedType(A, Type, Type);
> return false;
> }
>
> -bool Sema::checkNullabilityTypeSpecifier(QualType &type,
> - NullabilityKind nullability,
> - SourceLocation nullabilityLoc,
> - bool isContextSensitive,
> - bool allowOnArrayType) {
> - recordNullabilitySeen(*this, nullabilityLoc);
> +/// 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");
> + }
> +}
> +
> +/// 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();
> +
> + recordNullabilitySeen(S, nullabilityLoc);
>
> // Check for existing nullability attributes on the type.
> QualType desugared = type;
> @@ -6376,7 +6386,7 @@ bool Sema::checkNullabilityTypeSpecifier
> if (auto existingNullability = attributed->getImmediateNullability()) {
> // Duplicated nullability.
> if (nullability == *existingNullability) {
> - Diag(nullabilityLoc, diag::warn_nullability_duplicate)
> + S.Diag(nullabilityLoc, diag::warn_nullability_duplicate)
> << DiagNullabilityKind(nullability, isContextSensitive)
> << FixItHint::CreateRemoval(nullabilityLoc);
>
> @@ -6384,7 +6394,7 @@ bool Sema::checkNullabilityTypeSpecifier
> }
>
> // Conflicting nullability.
> - Diag(nullabilityLoc, diag::err_nullability_conflicting)
> + S.Diag(nullabilityLoc, diag::err_nullability_conflicting)
> << DiagNullabilityKind(nullability, isContextSensitive)
> << DiagNullabilityKind(*existingNullability, false);
> return true;
> @@ -6397,9 +6407,9 @@ bool Sema::checkNullabilityTypeSpecifier
> // 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(Context)) {
> + if (auto existingNullability = desugared->getNullability(S.Context)) {
> if (nullability != *existingNullability) {
> - Diag(nullabilityLoc, diag::err_nullability_conflicting)
> + S.Diag(nullabilityLoc, diag::err_nullability_conflicting)
> << DiagNullabilityKind(nullability, isContextSensitive)
> << DiagNullabilityKind(*existingNullability, false);
>
> @@ -6410,7 +6420,7 @@ bool Sema::checkNullabilityTypeSpecifier
> if (auto typedefNullability
> = AttributedType::stripOuterNullability(underlyingType)) {
> if (*typedefNullability == *existingNullability) {
> - Diag(typedefDecl->getLocation(), diag::note_nullability_here)
> + S.Diag(typedefDecl->getLocation(), diag::note_nullability_here)
> << DiagNullabilityKind(*existingNullability, false);
> }
> }
> @@ -6423,7 +6433,7 @@ bool Sema::checkNullabilityTypeSpecifier
> // If this definitely isn't a pointer type, reject the specifier.
> if (!desugared->canHaveNullability() &&
> !(allowOnArrayType && desugared->isArrayType())) {
> - Diag(nullabilityLoc, diag::err_nullability_nonpointer)
> + S.Diag(nullabilityLoc, diag::err_nullability_nonpointer)
> << DiagNullabilityKind(nullability, isContextSensitive) << type;
> return true;
> }
> @@ -6441,10 +6451,10 @@ bool Sema::checkNullabilityTypeSpecifier
> if (pointeeType->isAnyPointerType() ||
> pointeeType->isObjCObjectPointerType() ||
> pointeeType->isMemberPointerType()) {
> - Diag(nullabilityLoc, diag::err_nullability_cs_multilevel)
> + S.Diag(nullabilityLoc, diag::err_nullability_cs_multilevel)
> << DiagNullabilityKind(nullability, true)
> << type;
> - Diag(nullabilityLoc, diag::note_nullability_type_specifier)
> + S.Diag(nullabilityLoc, diag::note_nullability_type_specifier)
> << DiagNullabilityKind(nullability, false)
> << type
> << FixItHint::CreateReplacement(nullabilityLoc,
> @@ -6454,16 +6464,21 @@ bool Sema::checkNullabilityTypeSpecifier
> }
>
> // Form the attributed type.
> - type = Context.getAttributedType(
> - AttributedType::getNullabilityAttrKind(nullability), type, type);
> + type = state.getAttributedType(
> + createNullabilityAttr(S.Context, attr, nullability), type, type);
> return false;
> }
>
> -bool Sema::checkObjCKindOfType(QualType &type, SourceLocation loc) {
> +/// 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();
> +
> if (isa<ObjCTypeParamType>(type)) {
> // Build the attributed type to record where __kindof occurred.
> - type = Context.getAttributedType(AttributedType::attr_objc_kindof,
> - type, type);
> + type = state.getAttributedType(
> + createSimpleAttr<ObjCKindOfAttr>(S.Context, attr), type, type);
> return false;
> }
>
> @@ -6475,7 +6490,7 @@ bool Sema::checkObjCKindOfType(QualType
> // If not, we can't apply __kindof.
> if (!objType) {
> // FIXME: Handle dependent types that aren't yet object types.
> - Diag(loc, diag::err_objc_kindof_nonobject)
> + S.Diag(attr.getLoc(), diag::err_objc_kindof_nonobject)
> << type;
> return true;
> }
> @@ -6483,45 +6498,31 @@ bool Sema::checkObjCKindOfType(QualType
> // 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 = Context.getObjCObjectType(
> + QualType equivType = S.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 = Context.getObjCObjectPointerType(equivType);
> - if (auto nullability = type->getNullability(Context)) {
> - auto attrKind = AttributedType::getNullabilityAttrKind(*nullability);
> - equivType = Context.getAttributedType(attrKind, equivType, equivType);
> + 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);
> }
> }
>
> // Build the attributed type to record where __kindof occurred.
> - type = Context.getAttributedType(AttributedType::attr_objc_kindof,
> - type,
> - equivType);
> -
> + type = state.getAttributedType(
> + createSimpleAttr<ObjCKindOfAttr>(S.Context, attr), 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.
> @@ -6609,27 +6610,27 @@ static bool distributeNullabilityTypeAtt
> return false;
> }
>
> -static AttributedType::Kind getCCTypeAttrKind(ParsedAttr &Attr) {
> +static Attr *getCCTypeAttr(ASTContext &Ctx, ParsedAttr &Attr) {
> assert(!Attr.isInvalid());
> switch (Attr.getKind()) {
> default:
> llvm_unreachable("not a calling convention attribute");
> case ParsedAttr::AT_CDecl:
> - return AttributedType::attr_cdecl;
> + return createSimpleAttr<CDeclAttr>(Ctx, Attr);
> case ParsedAttr::AT_FastCall:
> - return AttributedType::attr_fastcall;
> + return createSimpleAttr<FastCallAttr>(Ctx, Attr);
> case ParsedAttr::AT_StdCall:
> - return AttributedType::attr_stdcall;
> + return createSimpleAttr<StdCallAttr>(Ctx, Attr);
> case ParsedAttr::AT_ThisCall:
> - return AttributedType::attr_thiscall;
> + return createSimpleAttr<ThisCallAttr>(Ctx, Attr);
> case ParsedAttr::AT_RegCall:
> - return AttributedType::attr_regcall;
> + return createSimpleAttr<RegCallAttr>(Ctx, Attr);
> case ParsedAttr::AT_Pascal:
> - return AttributedType::attr_pascal;
> + return createSimpleAttr<PascalAttr>(Ctx, Attr);
> case ParsedAttr::AT_SwiftCall:
> - return AttributedType::attr_swiftcall;
> + return createSimpleAttr<SwiftCallAttr>(Ctx, Attr);
> case ParsedAttr::AT_VectorCall:
> - return AttributedType::attr_vectorcall;
> + return createSimpleAttr<VectorCallAttr>(Ctx, Attr);
> 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,
> @@ -6639,20 +6640,22 @@ static AttributedType::Kind getCCTypeAtt
> Str = cast<StringLiteral>(Attr.getArgAsExpr(0))->getString();
> else
> Str = Attr.getArgAsIdent(0)->Ident->getName();
> - return llvm::StringSwitch<AttributedType::Kind>(Str)
> - .Case("aapcs", AttributedType::attr_pcs)
> - .Case("aapcs-vfp", AttributedType::attr_pcs_vfp);
> + PcsAttr::PCSType Type;
> + if (!PcsAttr::ConvertStrToPCSType(Str, Type))
> + llvm_unreachable("already validated the attribute");
> + return ::new (Ctx) PcsAttr(Attr.getRange(), Ctx, Type,
> + Attr.getAttributeSpellingListIndex());
> }
> case ParsedAttr::AT_IntelOclBicc:
> - return AttributedType::attr_inteloclbicc;
> + return createSimpleAttr<IntelOclBiccAttr>(Ctx, Attr);
> case ParsedAttr::AT_MSABI:
> - return AttributedType::attr_ms_abi;
> + return createSimpleAttr<MSABIAttr>(Ctx, Attr);
> case ParsedAttr::AT_SysVABI:
> - return AttributedType::attr_sysv_abi;
> + return createSimpleAttr<SysVABIAttr>(Ctx, Attr);
> case ParsedAttr::AT_PreserveMost:
> - return AttributedType::attr_preserve_most;
> + return createSimpleAttr<PreserveMostAttr>(Ctx, Attr);
> case ParsedAttr::AT_PreserveAll:
> - return AttributedType::attr_preserve_all;
> + return createSimpleAttr<PreserveAllAttr>(Ctx, Attr);
> }
> llvm_unreachable("unexpected attribute kind!");
> }
> @@ -6700,8 +6703,9 @@ static bool handleFunctionTypeAttr(TypeP
> = unwrapped.get()->getExtInfo().withProducesResult(true);
> type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
> }
> - type = S.Context.getAttributedType(AttributedType::attr_ns_returns_retained,
> - origType, type);
> + type = state.getAttributedType(
> + createSimpleAttr<NSReturnsRetainedAttr>(S.Context, attr),
> + origType, type);
> return true;
> }
>
> @@ -6776,13 +6780,12 @@ static bool handleFunctionTypeAttr(TypeP
>
> const FunctionType *fn = unwrapped.get();
> CallingConv CCOld = fn->getCallConv();
> - AttributedType::Kind CCAttrKind = getCCTypeAttrKind(attr);
> + Attr *CCAttr = getCCTypeAttr(S.Context, attr);
>
> if (CCOld != CC) {
> // Error out on when there's already an attribute on the type
> // and the CCs don't match.
> - const AttributedType *AT = S.getCallingConvAttributedType(type);
> - if (AT && AT->getAttrKind() != CCAttrKind) {
> + if (const AttributedType *AT = S.getCallingConvAttributedType(type)) {
> S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
> << FunctionType::getNameForCallConv(CC)
> << FunctionType::getNameForCallConv(CCOld);
> @@ -6836,7 +6839,7 @@ static bool handleFunctionTypeAttr(TypeP
> Equivalent =
> unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
> }
> - type = S.Context.getAttributedType(CCAttrKind, type, Equivalent);
> + type = state.getAttributedType(CCAttr, type, Equivalent);
> return true;
> }
>
> @@ -7192,14 +7195,15 @@ static void deduceOpenCLImplicitAddrSpac
> T = State.getSema().Context.getAddrSpaceQualType(T, ImpAddr);
> }
>
> -static void HandleLifetimeBoundAttr(QualType &CurType,
> - const ParsedAttr &Attr,
> - Sema &S, Declarator &D) {
> - if (D.isDeclarationOfFunction()) {
> - CurType = S.Context.getAttributedType(AttributedType::attr_lifetimebound,
> - CurType, CurType);
> +static void HandleLifetimeBoundAttr(TypeProcessingState &State,
> + QualType &CurType,
> + ParsedAttr &Attr) {
> + if (State.getDeclarator().isDeclarationOfFunction()) {
> + CurType = State.getAttributedType(
> + createSimpleAttr<LifetimeBoundAttr>(State.getSema().Context, Attr),
> + CurType, CurType);
> } else {
> - Attr.diagnoseAppertainsTo(S, nullptr);
> + Attr.diagnoseAppertainsTo(State.getSema(), nullptr);
> }
> }
>
> @@ -7309,11 +7313,8 @@ static void processTypeAttrs(TypeProcess
> attr.setUsedAsTypeAttr();
> break;
> case ParsedAttr::AT_LifetimeBound:
> - if (TAL == TAL_DeclChunk) {
> - HandleLifetimeBoundAttr(type, attr, state.getSema(),
> - state.getDeclarator());
> - attr.setUsedAsTypeAttr();
> - }
> + if (TAL == TAL_DeclChunk)
> + HandleLifetimeBoundAttr(state, type, attr);
> break;
>
> MS_TYPE_ATTRS_CASELIST:
> @@ -7337,11 +7338,10 @@ static void processTypeAttrs(TypeProcess
> bool allowOnArrayType =
> state.getDeclarator().isPrototypeContext() &&
> !hasOuterPointerLikeChunk(state.getDeclarator(), endIndex);
> - if (state.getSema().checkNullabilityTypeSpecifier(
> + if (checkNullabilityTypeSpecifier(
> + state,
> type,
> - mapNullabilityAttrKind(attr.getKind()),
> - attr.getLoc(),
> - attr.isContextSensitiveKeywordAttribute(),
> + attr,
> allowOnArrayType)) {
> attr.setInvalid();
> }
> @@ -7368,9 +7368,8 @@ static void processTypeAttrs(TypeProcess
> }
>
> // Apply it regardless.
> - if (state.getSema().checkObjCKindOfType(type, attr.getLoc()))
> + if (checkObjCKindOfType(state, type, attr))
> attr.setInvalid();
> - attr.setUsedAsTypeAttr();
> break;
>
> FUNCTION_TYPE_ATTRS_CASELIST:
>
> Modified: cfe/trunk/lib/Sema/TreeTransform.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=340215&r1=340214&r2=340215&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/TreeTransform.h (original)
> +++ cfe/trunk/lib/Sema/TreeTransform.h Mon Aug 20 14:47:29 2018
> @@ -6058,6 +6058,12 @@ QualType TreeTransform<Derived>::Transfo
> if (modifiedType.isNull())
> return QualType();
>
> + // oldAttr can be null if we started with a QualType rather than a TypeLoc.
> + const Attr *oldAttr = TL.getAttr();
> + const Attr *newAttr = oldAttr ? getDerived().TransformAttr(oldAttr) : nullptr;
> + if (oldAttr && !newAttr)
> + return QualType();
> +
> QualType result = TL.getType();
>
> // FIXME: dependent operand expressions?
> @@ -6074,26 +6080,20 @@ QualType TreeTransform<Derived>::Transfo
> // type sugar, and therefore cannot be diagnosed in any other way.
> if (auto nullability = oldType->getImmediateNullability()) {
> if (!modifiedType->canHaveNullability()) {
> - SemaRef.Diag(TL.getAttrNameLoc(), diag::err_nullability_nonpointer)
> - << DiagNullabilityKind(*nullability, false) << modifiedType;
> + SemaRef.Diag(TL.getAttr()->getLocation(),
> + diag::err_nullability_nonpointer)
> + << DiagNullabilityKind(*nullability, false) << modifiedType;
> return QualType();
> }
> }
>
> - result = SemaRef.Context.getAttributedType(oldType->getAttrKind(),
> + result = SemaRef.Context.getAttributedType(TL.getAttrKind(),
> modifiedType,
> equivalentType);
> }
>
> AttributedTypeLoc newTL = TLB.push<AttributedTypeLoc>(result);
> - 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());
> -
> + newTL.setAttr(newAttr);
> return result;
> }
>
>
> Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=340215&r1=340214&r2=340215&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTReader.cpp Mon Aug 20 14:47:29 2018
> @@ -6455,6 +6455,10 @@ class TypeLocReader : public TypeLocVisi
> return Reader->ReadNestedNameSpecifierLoc(*F, Record, Idx);
> }
>
> + Attr *ReadAttr() {
> + return Reader->ReadAttr(*F, Record, Idx);
> + }
> +
> public:
> TypeLocReader(ModuleFile &F, ASTReader &Reader,
> const ASTReader::RecordData &Record, unsigned &Idx)
> @@ -6646,20 +6650,7 @@ void TypeLocReader::VisitEnumTypeLoc(Enu
> }
>
> void TypeLocReader::VisitAttributedTypeLoc(AttributedTypeLoc TL) {
> - TL.setAttrNameLoc(ReadSourceLocation());
> - if (TL.hasAttrOperand()) {
> - SourceRange range;
> - range.setBegin(ReadSourceLocation());
> - range.setEnd(ReadSourceLocation());
> - TL.setAttrOperandParensRange(range);
> - }
> - if (TL.hasAttrExprOperand()) {
> - if (Record[Idx++])
> - TL.setAttrExprOperand(Reader->ReadExpr(*F));
> - else
> - TL.setAttrExprOperand(nullptr);
> - } else if (TL.hasAttrEnumOperand())
> - TL.setAttrEnumOperandLoc(ReadSourceLocation());
> + TL.setAttr(ReadAttr());
> }
>
> void TypeLocReader::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
>
> Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=340215&r1=340214&r2=340215&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Mon Aug 20 14:47:29 2018
> @@ -2648,19 +2648,72 @@ void ASTDeclReader::VisitOMPCapturedExpr
> // Attribute Reading
> //===----------------------------------------------------------------------===//
>
> -/// Reads attributes from the current stream position.
> -void ASTReader::ReadAttributes(ASTRecordReader &Record, AttrVec &Attrs) {
> - for (unsigned i = 0, e = Record.readInt(); i != e; ++i) {
> - Attr *New = nullptr;
> - auto Kind = (attr::Kind)Record.readInt();
> - SourceRange Range = Record.readSourceRange();
> - ASTContext &Context = getContext();
> +namespace {
> +class AttrReader {
> + ModuleFile *F;
> + ASTReader *Reader;
> + const ASTReader::RecordData &Record;
> + unsigned &Idx;
>
> -#include "clang/Serialization/AttrPCHRead.inc"
> +public:
> + AttrReader(ModuleFile &F, ASTReader &Reader,
> + const ASTReader::RecordData &Record, unsigned &Idx)
> + : F(&F), Reader(&Reader), Record(Record), Idx(Idx) {}
> +
> + const uint64_t &readInt() { return Record[Idx++]; }
> +
> + SourceRange readSourceRange() {
> + return Reader->ReadSourceRange(*F, Record, Idx);
> + }
> +
> + Expr *readExpr() { return Reader->ReadExpr(*F); }
> +
> + std::string readString() {
> + return Reader->ReadString(Record, Idx);
> + }
> +
> + TypeSourceInfo *getTypeSourceInfo() {
> + return Reader->GetTypeSourceInfo(*F, Record, Idx);
> + }
> +
> + IdentifierInfo *getIdentifierInfo() {
> + return Reader->GetIdentifierInfo(*F, Record, Idx);
> + }
>
> - assert(New && "Unable to decode attribute?");
> - Attrs.push_back(New);
> + VersionTuple readVersionTuple() {
> + return ASTReader::ReadVersionTuple(Record, Idx);
> }
> +
> + template <typename T> T *GetLocalDeclAs(uint32_t LocalID) {
> + return cast_or_null<T>(Reader->GetLocalDecl(*F, LocalID));
> + }
> +};
> +}
> +
> +Attr *ASTReader::ReadAttr(ModuleFile &M, const RecordData &Rec,
> + unsigned &Idx) {
> + AttrReader Record(M, *this, Rec, Idx);
> + auto V = Record.readInt();
> + if (!V)
> + return nullptr;
> +
> + Attr *New = nullptr;
> + // Kind is stored as a 1-based integer because 0 is used to indicate a null
> + // Attr pointer.
> + auto Kind = static_cast<attr::Kind>(V - 1);
> + SourceRange Range = Record.readSourceRange();
> + ASTContext &Context = getContext();
> +
> +#include "clang/Serialization/AttrPCHRead.inc"
> +
> + assert(New && "Unable to decode attribute?");
> + return New;
> +}
> +
> +/// Reads attributes from the current stream position.
> +void ASTReader::ReadAttributes(ASTRecordReader &Record, AttrVec &Attrs) {
> + for (unsigned I = 0, E = Record.readInt(); I != E; ++I)
> + Attrs.push_back(Record.readAttr());
> }
>
> //===----------------------------------------------------------------------===//
>
> Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=340215&r1=340214&r2=340215&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTWriter.cpp Mon Aug 20 14:47:29 2018
> @@ -770,19 +770,7 @@ void TypeLocWriter::VisitEnumTypeLoc(Enu
> }
>
> void TypeLocWriter::VisitAttributedTypeLoc(AttributedTypeLoc TL) {
> - Record.AddSourceLocation(TL.getAttrNameLoc());
> - if (TL.hasAttrOperand()) {
> - SourceRange range = TL.getAttrOperandParensRange();
> - Record.AddSourceLocation(range.getBegin());
> - Record.AddSourceLocation(range.getEnd());
> - }
> - if (TL.hasAttrExprOperand()) {
> - Expr *operand = TL.getAttrExprOperand();
> - Record.push_back(operand ? 1 : 0);
> - if (operand) Record.AddStmt(operand);
> - } else if (TL.hasAttrEnumOperand()) {
> - Record.AddSourceLocation(TL.getAttrEnumOperandLoc());
> - }
> + Record.AddAttr(TL.getAttr());
> }
>
> void TypeLocWriter::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
> @@ -4481,16 +4469,21 @@ void ASTWriter::WriteModuleFileExtension
> // General Serialization Routines
> //===----------------------------------------------------------------------===//
>
> -/// Emit the list of attributes to the specified record.
> -void ASTRecordWriter::AddAttributes(ArrayRef<const Attr *> Attrs) {
> +void ASTRecordWriter::AddAttr(const Attr *A) {
> auto &Record = *this;
> - Record.push_back(Attrs.size());
> - for (const auto *A : Attrs) {
> - Record.push_back(A->getKind()); // FIXME: stable encoding, target attrs
> - Record.AddSourceRange(A->getRange());
> + if (!A)
> + return Record.push_back(0);
> + Record.push_back(A->getKind() + 1); // FIXME: stable encoding, target attrs
> + Record.AddSourceRange(A->getRange());
>
> #include "clang/Serialization/AttrPCHWrite.inc"
> - }
> +}
> +
> +/// Emit the list of attributes to the specified record.
> +void ASTRecordWriter::AddAttributes(ArrayRef<const Attr *> Attrs) {
> + push_back(Attrs.size());
> + for (const auto *A : Attrs)
> + AddAttr(A);
> }
>
> void ASTWriter::AddToken(const Token &Tok, RecordDataImpl &Record) {
>
> Modified: cfe/trunk/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CheckerHelpers.cpp?rev=340215&r1=340214&r2=340215&view=diff
> ==============================================================================
> --- cfe/trunk/lib/StaticAnalyzer/Core/CheckerHelpers.cpp (original)
> +++ cfe/trunk/lib/StaticAnalyzer/Core/CheckerHelpers.cpp Mon Aug 20 14:47:29 2018
> @@ -103,9 +103,9 @@ Nullability getNullabilityAnnotation(Qua
> const auto *AttrType = Type->getAs<AttributedType>();
> if (!AttrType)
> return Nullability::Unspecified;
> - if (AttrType->getAttrKind() == AttributedType::attr_nullable)
> + if (AttrType->getAttrKind() == attr::TypeNullable)
> return Nullability::Nullable;
> - else if (AttrType->getAttrKind() == AttributedType::attr_nonnull)
> + else if (AttrType->getAttrKind() == attr::TypeNonNull)
> return Nullability::Nonnull;
> return Nullability::Unspecified;
> }
>
> Modified: cfe/trunk/test/SemaCXX/calling-conv-compat.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/calling-conv-compat.cpp?rev=340215&r1=340214&r2=340215&view=diff
> ==============================================================================
> --- cfe/trunk/test/SemaCXX/calling-conv-compat.cpp (original)
> +++ cfe/trunk/test/SemaCXX/calling-conv-compat.cpp Mon Aug 20 14:47:29 2018
> @@ -1,4 +1,8 @@
> // RUN: %clang_cc1 -fsyntax-only -std=c++11 -fms-extensions -verify -triple i686-pc-win32 %s
> +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -fms-extensions -verify -triple x86_64-pc-win32 %s
> +
> +// FIXME: Extend this portion of the test to cover the 64-bit case.
> +#if !_M_X64
>
> // Pointers to free functions
> void free_func_default();
> @@ -244,11 +248,16 @@ void call_member_inheritance() {
> }
> } // end namespace NonVariadic
>
> +#endif // !_M_X64
> +
> namespace Variadic {
> struct A {
> void member_default(int, ...);
> void __cdecl member_cdecl(int, ...);
> - void __thiscall member_thiscall(int, ...); // expected-error {{variadic function cannot use thiscall calling convention}}
> + void __thiscall member_thiscall(int, ...);
> +#if !_M_X64
> + // expected-error at -2 {{variadic function cannot use thiscall calling convention}}
> +#endif
> };
>
> struct B : public A {
> @@ -319,7 +328,10 @@ mptr_t __stdcall return_mptr_std(short)
> }
>
> void (A::*(*return_fptr_std_mptr(char))(short))(int) {
> - return return_mptr_std; // expected-error {{cannot initialize return object of type 'void (MultiChunkDecls::A::*(*)(short))(int) __attribute__((thiscall))' with an lvalue of type 'MultiChunkDecls::mptr_t (short) __attribute__((stdcall))'}}
> + return return_mptr_std;
> +#if !_M_X64
> + // expected-error at -2 {{cannot initialize return object of type 'void (MultiChunkDecls::A::*(*)(short))(int) __attribute__((thiscall))' with an lvalue of type 'MultiChunkDecls::mptr_t (short) __attribute__((stdcall))'}}
> +#endif
> }
>
> void call_return() {
> @@ -387,15 +399,32 @@ Y<decltype(&A::method_thiscall)>::p tmpl
>
> // Test that lambdas that capture nothing convert to cdecl function pointers.
> namespace Lambdas {
> -
> void pass_fptr_cdecl (void (__cdecl *fp)());
> -void pass_fptr_stdcall (void (__stdcall *fp)()); // expected-note {{candidate function not viable}}
> -void pass_fptr_fastcall(void (__fastcall *fp)()); // expected-note {{candidate function not viable}}
> +void pass_fptr_stdcall (void (__stdcall *fp)());
> +void pass_fptr_fastcall(void (__fastcall *fp)());
>
> void conversion_to_fptr() {
> pass_fptr_cdecl ([]() { } );
> - pass_fptr_stdcall ([]() { } ); // expected-error {{no matching function for call}}
> - pass_fptr_fastcall([]() { } ); // expected-error {{no matching function for call}}
> +
> + pass_fptr_stdcall ([]() { } );
> +#if !_M_X64
> + // expected-error at -2 {{no matching function for call}}
> + // expected-note at -9 {{candidate function not viable}}
> +#endif
> +
> + pass_fptr_fastcall([]() { } );
> +#if !_M_X64
> + // expected-error at -2 {{no matching function for call}}
> + // expected-note at -14 {{candidate function not viable}}
> +#endif
> +}
> }
>
> +namespace D50526 {
> + template<typename T, T (__stdcall f)()> void g();
> + void h() { g<void, h>(); }
> +#if !_M_X64
> + // expected-error at -2 {{no matching function for call to}}
> + // expected-note at -4 {{invalid explicitly-specified argument}}
> +#endif
> }
>
> Modified: cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?rev=340215&r1=340214&r2=340215&view=diff
> ==============================================================================
> --- cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp (original)
> +++ cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp Mon Aug 20 14:47:29 2018
> @@ -2470,8 +2470,10 @@ namespace {
>
> static const AttrClassDescriptor AttrClassDescriptors[] = {
> { "ATTR", "Attr" },
> + { "TYPE_ATTR", "TypeAttr" },
> { "STMT_ATTR", "StmtAttr" },
> { "INHERITABLE_ATTR", "InheritableAttr" },
> + { "DECL_OR_TYPE_ATTR", "DeclOrTypeAttr" },
> { "INHERITABLE_PARAM_ATTR", "InheritableParamAttr" },
> { "PARAMETER_ABI_ATTR", "ParameterABIAttr" }
> };
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
More information about the cfe-commits
mailing list