diff options
author | Daniel Dunbar <daniel@zuster.org> | 2012-03-06 18:20:20 +0000 |
---|---|---|
committer | Daniel Dunbar <daniel@zuster.org> | 2012-03-06 18:20:20 +0000 |
commit | f9aa3635fccb3dc0925ef4d27dfa2b692a8e6a90 (patch) | |
tree | 86f79fa8d49322025b4b307166b9e73abe036cab | |
parent | 81e722e2c1195a90825ceaaa90f4a14b7df09b41 (diff) |
AST: Move several Type::is...Type() functions to be inline.
- These functions are both (a) very commonly called and (b) excellent
candidates for CSE in the callers in which they are commonly used.
- That isHalfType() is hot makes me sad, but it is trivially when inlined (and
a huge waste of time when not!!!).
- The extra IsEnumDeclComplete() function is a hack to break the cycle between
Type.h and Decl.h, I'm not sure of how to do this more cleanly, but am open
to ideas.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@152126 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/AST/Decl.h | 10 | ||||
-rw-r--r-- | include/clang/AST/Type.h | 49 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 61 |
3 files changed, 67 insertions, 53 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 8715067ce6..ecb8794174 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -3273,6 +3273,16 @@ void Redeclarable<decl_type>::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/include/clang/AST/Type.h b/include/clang/AST/Type.h index 8146d7b6f1..1b00594d6b 100644 --- a/include/clang/AST/Type.h +++ b/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<BuiltinType>(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<BuiltinType>()) + return BT->getKind() == BuiltinType::NullPtr; + return false; +} + +extern bool IsEnumDeclComplete(EnumDecl *); + +inline bool Type::isScalarType() const { + if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) + return BT->getKind() > BuiltinType::Void && + BT->getKind() <= BuiltinType::NullPtr; + if (const EnumType *ET = dyn_cast<EnumType>(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<PointerType>(CanonicalType) || + isa<BlockPointerType>(CanonicalType) || + isa<MemberPointerType>(CanonicalType) || + isa<ComplexType>(CanonicalType) || + isa<ObjCObjectPointerType>(CanonicalType); +} + +inline bool Type::isIntegralOrEnumerationType() const { + if (const BuiltinType *BT = dyn_cast<BuiltinType>(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<EnumType>(CanonicalType)) + return IsEnumDeclComplete(ET->getDecl()); + + return false; +} + +inline bool Type::isBooleanType() const { + if (const BuiltinType *BT = dyn_cast<BuiltinType>(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/lib/AST/Type.cpp b/lib/AST/Type.cpp index c58debbbd2..ce805617f8 100644 --- a/lib/AST/Type.cpp +++ b/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<BuiltinType>(CanonicalType)) - return BT->getKind() >= BuiltinType::Bool && - BT->getKind() <= BuiltinType::Int128; - if (const EnumType *ET = dyn_cast<EnumType>(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<VectorType>(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<BuiltinType>(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<EnumType>(CanonicalType)) - return ET->getDecl()->isComplete(); - - return false; -} bool Type::isIntegralOrUnscopedEnumerationType() const { if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) @@ -634,9 +611,15 @@ bool Type::isIntegralOrUnscopedEnumerationType() const { } -bool Type::isBooleanType() const { + +bool Type::isIntegerType() const { if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) - return BT->getKind() == BuiltinType::Bool; + return BT->getKind() >= BuiltinType::Bool && + BT->getKind() <= BuiltinType::Int128; + if (const EnumType *ET = dyn_cast<EnumType>(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<BuiltinType>(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<BuiltinType>(CanonicalType)) return BT->getKind() >= BuiltinType::Half && @@ -820,21 +796,6 @@ bool Type::isArithmeticType() const { return isa<ComplexType>(CanonicalType); } -bool Type::isScalarType() const { - if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) - return BT->getKind() > BuiltinType::Void && - BT->getKind() <= BuiltinType::NullPtr; - if (const EnumType *ET = dyn_cast<EnumType>(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<PointerType>(CanonicalType) || - isa<BlockPointerType>(CanonicalType) || - isa<MemberPointerType>(CanonicalType) || - isa<ComplexType>(CanonicalType) || - isa<ObjCObjectPointerType>(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<BuiltinType>()) - return BT->getKind() == BuiltinType::NullPtr; - return false; -} - bool Type::isSpecifierType() const { // Note that this intentionally does not use the canonical type. switch (getTypeClass()) { |