diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 8715067ce659..ecb879417438 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -3273,6 +3273,16 @@ void Redeclarable::setPreviousDeclaration(decl_type *PrevDecl) { ND->ClearLinkageCache(); } +// Inline function definitions. + +/// \brief Check if the given decl is complete. +/// +/// We use this function to break a cycle between the inline definitions in +/// Type.h and Decl.h. +inline bool IsEnumDeclComplete(EnumDecl *ED) { + return ED->isComplete(); +} + } // end namespace clang #endif diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 8146d7b6f116..1b00594d6bdb 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -4816,6 +4816,55 @@ inline bool Type::isNonOverloadPlaceholderType() const { return false; } +inline bool Type::isHalfType() const { + if (const BuiltinType *BT = dyn_cast(CanonicalType)) + return BT->getKind() == BuiltinType::Half; + // FIXME: Should we allow complex __fp16? Probably not. + return false; +} + +inline bool Type::isNullPtrType() const { + if (const BuiltinType *BT = getAs()) + return BT->getKind() == BuiltinType::NullPtr; + return false; +} + +extern bool IsEnumDeclComplete(EnumDecl *); + +inline bool Type::isScalarType() const { + if (const BuiltinType *BT = dyn_cast(CanonicalType)) + return BT->getKind() > BuiltinType::Void && + BT->getKind() <= BuiltinType::NullPtr; + if (const EnumType *ET = dyn_cast(CanonicalType)) + // Enums are scalar types, but only if they are defined. Incomplete enums + // are not treated as scalar types. + return IsEnumDeclComplete(ET->getDecl()); + return isa(CanonicalType) || + isa(CanonicalType) || + isa(CanonicalType) || + isa(CanonicalType) || + isa(CanonicalType); +} + +inline bool Type::isIntegralOrEnumerationType() const { + if (const BuiltinType *BT = dyn_cast(CanonicalType)) + return BT->getKind() >= BuiltinType::Bool && + BT->getKind() <= BuiltinType::Int128; + + // Check for a complete enum type; incomplete enum types are not properly an + // enumeration type in the sense required here. + if (const EnumType *ET = dyn_cast(CanonicalType)) + return IsEnumDeclComplete(ET->getDecl()); + + return false; +} + +inline bool Type::isBooleanType() const { + if (const BuiltinType *BT = dyn_cast(CanonicalType)) + return BT->getKind() == BuiltinType::Bool; + return false; +} + /// \brief Determines whether this is a type for which one can define /// an overloaded operator. inline bool Type::isOverloadableType() const { diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index c58debbbd27b..ce805617f89d 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -556,17 +556,6 @@ AutoType *Type::getContainedAutoType() const { return GetContainedAutoVisitor().Visit(this); } -bool Type::isIntegerType() const { - if (const BuiltinType *BT = dyn_cast(CanonicalType)) - return BT->getKind() >= BuiltinType::Bool && - BT->getKind() <= BuiltinType::Int128; - if (const EnumType *ET = dyn_cast(CanonicalType)) - // Incomplete enum types are not treated as integer types. - // FIXME: In C++, enum types are never integer types. - return ET->getDecl()->isComplete() && !ET->getDecl()->isScoped(); - return false; -} - bool Type::hasIntegerRepresentation() const { if (const VectorType *VT = dyn_cast(CanonicalType)) return VT->getElementType()->isIntegerType(); @@ -605,18 +594,6 @@ bool Type::isIntegralType(ASTContext &Ctx) const { return false; } -bool Type::isIntegralOrEnumerationType() const { - if (const BuiltinType *BT = dyn_cast(CanonicalType)) - return BT->getKind() >= BuiltinType::Bool && - BT->getKind() <= BuiltinType::Int128; - - // Check for a complete enum type; incomplete enum types are not properly an - // enumeration type in the sense required here. - if (const EnumType *ET = dyn_cast(CanonicalType)) - return ET->getDecl()->isComplete(); - - return false; -} bool Type::isIntegralOrUnscopedEnumerationType() const { if (const BuiltinType *BT = dyn_cast(CanonicalType)) @@ -634,9 +611,15 @@ bool Type::isIntegralOrUnscopedEnumerationType() const { } -bool Type::isBooleanType() const { + +bool Type::isIntegerType() const { if (const BuiltinType *BT = dyn_cast(CanonicalType)) - return BT->getKind() == BuiltinType::Bool; + return BT->getKind() >= BuiltinType::Bool && + BT->getKind() <= BuiltinType::Int128; + if (const EnumType *ET = dyn_cast(CanonicalType)) + // Incomplete enum types are not treated as integer types. + // FIXME: In C++, enum types are never integer types. + return ET->getDecl()->isComplete() && !ET->getDecl()->isScoped(); return false; } @@ -767,13 +750,6 @@ bool Type::hasUnsignedIntegerRepresentation() const { return isUnsignedIntegerType(); } -bool Type::isHalfType() const { - if (const BuiltinType *BT = dyn_cast(CanonicalType)) - return BT->getKind() == BuiltinType::Half; - // FIXME: Should we allow complex __fp16? Probably not. - return false; -} - bool Type::isFloatingType() const { if (const BuiltinType *BT = dyn_cast(CanonicalType)) return BT->getKind() >= BuiltinType::Half && @@ -820,21 +796,6 @@ bool Type::isArithmeticType() const { return isa(CanonicalType); } -bool Type::isScalarType() const { - if (const BuiltinType *BT = dyn_cast(CanonicalType)) - return BT->getKind() > BuiltinType::Void && - BT->getKind() <= BuiltinType::NullPtr; - if (const EnumType *ET = dyn_cast(CanonicalType)) - // Enums are scalar types, but only if they are defined. Incomplete enums - // are not treated as scalar types. - return ET->getDecl()->isComplete(); - return isa(CanonicalType) || - isa(CanonicalType) || - isa(CanonicalType) || - isa(CanonicalType) || - isa(CanonicalType); -} - Type::ScalarTypeKind Type::getScalarTypeKind() const { assert(isScalarType()); @@ -1312,12 +1273,6 @@ bool Type::isPromotableIntegerType() const { return false; } -bool Type::isNullPtrType() const { - if (const BuiltinType *BT = getAs()) - return BT->getKind() == BuiltinType::NullPtr; - return false; -} - bool Type::isSpecifierType() const { // Note that this intentionally does not use the canonical type. switch (getTypeClass()) {