aboutsummaryrefslogtreecommitdiff
path: root/include/clang/AST/Type.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/AST/Type.h')
-rw-r--r--include/clang/AST/Type.h208
1 files changed, 173 insertions, 35 deletions
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index a50e054f9b28..bd30aad10f27 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -333,6 +333,20 @@ public:
bool hasAddressSpace() const { return Mask & AddressSpaceMask; }
unsigned getAddressSpace() const { return Mask >> AddressSpaceShift; }
+ /// Get the address space attribute value to be printed by diagnostics.
+ unsigned getAddressSpaceAttributePrintValue() const {
+ auto Addr = getAddressSpace();
+ // This function is not supposed to be used with language specific
+ // address spaces. If that happens, the diagnostic message should consider
+ // printing the QualType instead of the address space value.
+ assert(Addr == 0 || Addr >= LangAS::Count);
+ if (Addr)
+ return Addr - LangAS::Count;
+ // TODO: The diagnostic messages where Addr may be 0 should be fixed
+ // since it cannot differentiate the situation where 0 denotes the default
+ // address space or user specified __attribute__((address_space(0))).
+ return 0;
+ }
void setAddressSpace(unsigned space) {
assert(space <= MaxAddressSpace);
Mask = (Mask & ~AddressSpaceMask)
@@ -1020,6 +1034,9 @@ public:
return getQualifiers().hasStrongOrWeakObjCLifetime();
}
+ // true when Type is objc's weak and weak is enabled but ARC isn't.
+ bool isNonWeakInMRRWithObjCWeak(const ASTContext &Context) const;
+
enum DestructionKind {
DK_none,
DK_cxx_destructor,
@@ -1744,7 +1761,6 @@ public:
bool isEventT() const; // OpenCL event_t
bool isClkEventT() const; // OpenCL clk_event_t
bool isQueueT() const; // OpenCL queue_t
- bool isNDRangeT() const; // OpenCL ndrange_t
bool isReserveIDT() const; // OpenCL reserve_id_t
bool isPipeType() const; // OpenCL pipe type
@@ -1785,7 +1801,8 @@ public:
}
/// \brief Determine whether this type is an undeduced type, meaning that
- /// it somehow involves a C++11 'auto' type which has not yet been deduced.
+ /// it somehow involves a C++11 'auto' type or similar which has not yet been
+ /// deduced.
bool isUndeducedType() const;
/// \brief Whether this type is a variably-modified type (C99 6.7.5).
@@ -1862,10 +1879,22 @@ public:
/// not refer to a CXXRecordDecl, returns NULL.
const CXXRecordDecl *getPointeeCXXRecordDecl() const;
+ /// Get the DeducedType whose type will be deduced for a variable with
+ /// an initializer of this type. This looks through declarators like pointer
+ /// types, but not through decltype or typedefs.
+ DeducedType *getContainedDeducedType() const;
+
/// Get the AutoType whose type will be deduced for a variable with
/// an initializer of this type. This looks through declarators like pointer
/// types, but not through decltype or typedefs.
- AutoType *getContainedAutoType() const;
+ AutoType *getContainedAutoType() const {
+ return dyn_cast_or_null<AutoType>(getContainedDeducedType());
+ }
+
+ /// Determine whether this type was written with a leading 'auto'
+ /// corresponding to a trailing return type (possibly for a nested
+ /// function type within a pointer to function type or similar).
+ bool hasAutoForTrailingReturnType() const;
/// Member-template getAs<specific type>'. Look through sugar for
/// an instance of \<specific type>. This scheme will eventually
@@ -1875,6 +1904,13 @@ public:
/// immediately following this class.
template <typename T> const T *getAs() const;
+ /// Member-template getAsAdjusted<specific type>. Look through specific kinds
+ /// of sugar (parens, attributes, etc) for an instance of \<specific type>.
+ /// This is used when you need to walk over sugar nodes that represent some
+ /// kind of type adjustment from a type that was written as a \<specific type>
+ /// to another type that is still canonically a \<specific type>.
+ template <typename T> const T *getAsAdjusted() const;
+
/// A variant of getAs<> for array types which silently discards
/// qualifiers from the outermost type.
const ArrayType *getAsArrayTypeUnsafe() const;
@@ -2057,7 +2093,7 @@ public:
: Type(Builtin, QualType(), /*Dependent=*/(K == Dependent),
/*InstantiationDependent=*/(K == Dependent),
/*VariablyModified=*/false,
- /*Unexpanded paramter pack=*/false) {
+ /*Unexpanded parameter pack=*/false) {
BuiltinTypeBits.Kind = K;
}
@@ -3097,9 +3133,11 @@ public:
class ExtParameterInfo {
enum {
ABIMask = 0x0F,
- IsConsumed = 0x10
+ IsConsumed = 0x10,
+ HasPassObjSize = 0x20,
};
unsigned char Data;
+
public:
ExtParameterInfo() : Data(0) {}
@@ -3128,6 +3166,15 @@ public:
return copy;
}
+ bool hasPassObjectSize() const {
+ return Data & HasPassObjSize;
+ }
+ ExtParameterInfo withHasPassObjectSize() const {
+ ExtParameterInfo Copy = *this;
+ Copy.Data |= HasPassObjSize;
+ return Copy;
+ }
+
unsigned char getOpaqueValue() const { return Data; }
static ExtParameterInfo getFromOpaqueValue(unsigned char data) {
ExtParameterInfo result;
@@ -4089,43 +4136,41 @@ public:
}
};
-/// \brief Represents a C++11 auto or C++14 decltype(auto) type.
+/// \brief Common base class for placeholders for types that get replaced by
+/// placeholder type deduction: C++11 auto, C++14 decltype(auto), C++17 deduced
+/// class template types, and (eventually) constrained type names from the C++
+/// Concepts TS.
///
/// These types are usually a placeholder for a deduced type. However, before
/// the initializer is attached, or (usually) if the initializer is
-/// type-dependent, there is no deduced type and an auto type is canonical. In
+/// type-dependent, there is no deduced type and the type is canonical. In
/// the latter case, it is also a dependent type.
-class AutoType : public Type, public llvm::FoldingSetNode {
- AutoType(QualType DeducedType, AutoTypeKeyword Keyword, bool IsDependent)
- : Type(Auto, DeducedType.isNull() ? QualType(this, 0) : DeducedType,
- /*Dependent=*/IsDependent, /*InstantiationDependent=*/IsDependent,
- /*VariablyModified=*/false, /*ContainsParameterPack=*/false) {
- if (!DeducedType.isNull()) {
- if (DeducedType->isDependentType())
+class DeducedType : public Type {
+protected:
+ DeducedType(TypeClass TC, QualType DeducedAsType, bool IsDependent,
+ bool IsInstantiationDependent, bool ContainsParameterPack)
+ : Type(TC,
+ // FIXME: Retain the sugared deduced type?
+ DeducedAsType.isNull() ? QualType(this, 0)
+ : DeducedAsType.getCanonicalType(),
+ IsDependent, IsInstantiationDependent,
+ /*VariablyModified=*/false, ContainsParameterPack) {
+ if (!DeducedAsType.isNull()) {
+ if (DeducedAsType->isDependentType())
setDependent();
- if (DeducedType->isInstantiationDependentType())
+ if (DeducedAsType->isInstantiationDependentType())
setInstantiationDependent();
- if (DeducedType->containsUnexpandedParameterPack())
+ if (DeducedAsType->containsUnexpandedParameterPack())
setContainsUnexpandedParameterPack();
}
- AutoTypeBits.Keyword = (unsigned)Keyword;
}
- friend class ASTContext; // ASTContext creates these
-
public:
- bool isDecltypeAuto() const {
- return getKeyword() == AutoTypeKeyword::DecltypeAuto;
- }
- AutoTypeKeyword getKeyword() const {
- return (AutoTypeKeyword)AutoTypeBits.Keyword;
- }
-
bool isSugared() const { return !isCanonicalUnqualified(); }
QualType desugar() const { return getCanonicalTypeInternal(); }
- /// \brief Get the type deduced for this auto type, or null if it's either
- /// not been deduced or was deduced to a dependent type.
+ /// \brief Get the type deduced for this placeholder type, or null if it's
+ /// either not been deduced or was deduced to a dependent type.
QualType getDeducedType() const {
return !isCanonicalUnqualified() ? getCanonicalTypeInternal() : QualType();
}
@@ -4133,6 +4178,31 @@ public:
return !isCanonicalUnqualified() || isDependentType();
}
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == Auto ||
+ T->getTypeClass() == DeducedTemplateSpecialization;
+ }
+};
+
+/// \brief Represents a C++11 auto or C++14 decltype(auto) type.
+class AutoType : public DeducedType, public llvm::FoldingSetNode {
+ AutoType(QualType DeducedAsType, AutoTypeKeyword Keyword,
+ bool IsDeducedAsDependent)
+ : DeducedType(Auto, DeducedAsType, IsDeducedAsDependent,
+ IsDeducedAsDependent, /*ContainsPack=*/false) {
+ AutoTypeBits.Keyword = (unsigned)Keyword;
+ }
+
+ friend class ASTContext; // ASTContext creates these
+
+public:
+ bool isDecltypeAuto() const {
+ return getKeyword() == AutoTypeKeyword::DecltypeAuto;
+ }
+ AutoTypeKeyword getKeyword() const {
+ return (AutoTypeKeyword)AutoTypeBits.Keyword;
+ }
+
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getDeducedType(), getKeyword(), isDependentType());
}
@@ -4149,6 +4219,43 @@ public:
}
};
+/// \brief Represents a C++17 deduced template specialization type.
+class DeducedTemplateSpecializationType : public DeducedType,
+ public llvm::FoldingSetNode {
+ /// The name of the template whose arguments will be deduced.
+ TemplateName Template;
+
+ DeducedTemplateSpecializationType(TemplateName Template,
+ QualType DeducedAsType,
+ bool IsDeducedAsDependent)
+ : DeducedType(DeducedTemplateSpecialization, DeducedAsType,
+ IsDeducedAsDependent || Template.isDependent(),
+ IsDeducedAsDependent || Template.isInstantiationDependent(),
+ Template.containsUnexpandedParameterPack()),
+ Template(Template) {}
+
+ friend class ASTContext; // ASTContext creates these
+
+public:
+ /// Retrieve the name of the template that we are deducing.
+ TemplateName getTemplateName() const { return Template;}
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getTemplateName(), getDeducedType(), isDependentType());
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, TemplateName Template,
+ QualType Deduced, bool IsDependent) {
+ Template.Profile(ID);
+ ID.AddPointer(Deduced.getAsOpaquePtr());
+ ID.AddBoolean(IsDependent);
+ }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == DeducedTemplateSpecialization;
+ }
+};
+
/// \brief Represents a type template specialization; the template
/// must be a class template, a type alias template, or a template
/// template parameter. A template which cannot be resolved to one of
@@ -4345,6 +4452,9 @@ public:
const TemplateSpecializationType *getInjectedTST() const {
return cast<TemplateSpecializationType>(InjectedType.getTypePtr());
}
+ TemplateName getTemplateName() const {
+ return getInjectedTST()->getTemplateName();
+ }
CXXRecordDecl *getDecl() const;
@@ -5718,10 +5828,6 @@ inline bool Type::isQueueT() const {
return isSpecificBuiltinType(BuiltinType::OCLQueue);
}
-inline bool Type::isNDRangeT() const {
- return isSpecificBuiltinType(BuiltinType::OCLNDRange);
-}
-
inline bool Type::isReserveIDT() const {
return isSpecificBuiltinType(BuiltinType::OCLReserveID);
}
@@ -5739,7 +5845,7 @@ inline bool Type::isPipeType() const {
inline bool Type::isOpenCLSpecificType() const {
return isSamplerT() || isEventT() || isImageType() || isClkEventT() ||
- isQueueT() || isNDRangeT() || isReserveIDT() || isPipeType();
+ isQueueT() || isReserveIDT() || isPipeType();
}
inline bool Type::isTemplateTypeParmType() const {
@@ -5849,8 +5955,8 @@ inline bool Type::isBooleanType() const {
}
inline bool Type::isUndeducedType() const {
- const AutoType *AT = getContainedAutoType();
- return AT && !AT->isDeduced();
+ auto *DT = getContainedDeducedType();
+ return DT && !DT->isDeduced();
}
/// \brief Determines whether this is a type for which one can define
@@ -5932,6 +6038,38 @@ template <typename T> const T *Type::getAs() const {
return cast<T>(getUnqualifiedDesugaredType());
}
+template <typename T> const T *Type::getAsAdjusted() const {
+ static_assert(!TypeIsArrayType<T>::value, "ArrayType cannot be used with getAsAdjusted!");
+
+ // If this is directly a T type, return it.
+ if (const T *Ty = dyn_cast<T>(this))
+ return Ty;
+
+ // If the canonical form of this type isn't the right kind, reject it.
+ if (!isa<T>(CanonicalType))
+ return nullptr;
+
+ // Strip off type adjustments that do not modify the underlying nature of the
+ // type.
+ const Type *Ty = this;
+ while (Ty) {
+ if (const auto *A = dyn_cast<AttributedType>(Ty))
+ Ty = A->getModifiedType().getTypePtr();
+ else if (const auto *E = dyn_cast<ElaboratedType>(Ty))
+ Ty = E->desugar().getTypePtr();
+ else if (const auto *P = dyn_cast<ParenType>(Ty))
+ Ty = P->desugar().getTypePtr();
+ else if (const auto *A = dyn_cast<AdjustedType>(Ty))
+ Ty = A->desugar().getTypePtr();
+ else
+ break;
+ }
+
+ // Just because the canonical type is correct does not mean we can use cast<>,
+ // since we may not have stripped off all the sugar down to the base type.
+ return dyn_cast<T>(Ty);
+}
+
inline const ArrayType *Type::getAsArrayTypeUnsafe() const {
// If this is directly an array type, return it.
if (const ArrayType *arr = dyn_cast<ArrayType>(this))