mirror of
https://github.com/intel/llvm.git
synced 2026-01-26 12:26:52 +08:00
Introduce the canonical type smart pointers, and use them in a few places to
tighten up the static type system. llvm-svn: 78164
This commit is contained in:
@@ -22,6 +22,7 @@
|
||||
#include "clang/AST/PrettyPrinter.h"
|
||||
#include "clang/AST/TemplateName.h"
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/AST/CanonicalType.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
@@ -700,7 +701,7 @@ public:
|
||||
/// include typedefs, 'typeof' operators, etc. The returned type is guaranteed
|
||||
/// to be free of any of these, allowing two canonical types to be compared
|
||||
/// for exact equality with a simple pointer comparison.
|
||||
QualType getCanonicalType(QualType T);
|
||||
CanQualType getCanonicalType(QualType T);
|
||||
const Type *getCanonicalType(const Type *T) {
|
||||
return T->getCanonicalTypeInternal().getTypePtr();
|
||||
}
|
||||
|
||||
746
clang/include/clang/AST/CanonicalType.h
Normal file
746
clang/include/clang/AST/CanonicalType.h
Normal file
@@ -0,0 +1,746 @@
|
||||
//===-- CanonicalType.h - C Language Family Type Representation -*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the CanQual class template, which provides access to
|
||||
// canonical types.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_AST_CANONICAL_TYPE_H
|
||||
#define LLVM_CLANG_AST_CANONICAL_TYPE_H
|
||||
|
||||
#include "clang/AST/Type.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/type_traits.h"
|
||||
#include <iterator>
|
||||
|
||||
namespace clang {
|
||||
|
||||
template<typename T> class CanProxy;
|
||||
template<typename T> struct CanProxyAdaptor;
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// Canonical, qualified type template
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
/// \brief Represents a canonical, potentially-qualified type.
|
||||
///
|
||||
/// The CanQual template is a lightweight smart pointer that provides access
|
||||
/// to the canonical representation of a type, where all typedefs and other
|
||||
/// syntactic sugar has been eliminated. A CanQualType may also have various
|
||||
/// qualifiers (const, volatile, restrict) attached to it.
|
||||
///
|
||||
/// The template type parameter @p T is one of the Type classes (PointerType,
|
||||
/// BuiltinType, etc.). The type stored within @c CanQual<T> will be of that
|
||||
/// type (or some subclass of that type). The typedef @c CanQualType is just
|
||||
/// a shorthand for @c CanQual<Type>.
|
||||
///
|
||||
/// An instance of @c CanQual<T> can be implicitly converted to a
|
||||
/// @c CanQual<U> when T is derived from U, which essentially provides an
|
||||
/// implicit upcast. For example, @c CanQual<LValueReferenceType> can be
|
||||
/// converted to @c CanQual<ReferenceType>. Note that any @c CanQual type can
|
||||
/// be implicitly converted to a QualType, but the reverse operation requires
|
||||
/// a call to ASTContext::getCanonicalType().
|
||||
///
|
||||
///
|
||||
template<typename T = Type>
|
||||
class CanQual {
|
||||
/// \brief The actual, canonical type.
|
||||
QualType Stored;
|
||||
|
||||
public:
|
||||
/// \brief Constructs a NULL canonical type.
|
||||
CanQual() : Stored() { }
|
||||
|
||||
/// \brief Converting constructor that permits implicit upcasting of
|
||||
/// canonical type pointers.
|
||||
template<typename U>
|
||||
CanQual(const CanQual<U>& Other,
|
||||
typename llvm::enable_if<llvm::is_base_of<T, U>, int>::type = 0);
|
||||
|
||||
/// \brief Implicit conversion to the underlying pointer.
|
||||
///
|
||||
/// Also provides the ability to use canonical types in a boolean context,
|
||||
/// e.g.,
|
||||
/// @code
|
||||
/// if (CanQual<PointerType> Ptr = T->getAs<PointerType>()) { ... }
|
||||
/// @endcode
|
||||
operator const T*() const { return getTypePtr(); }
|
||||
|
||||
/// \brief Retrieve the underlying type pointer, which refers to a
|
||||
/// canonical type.
|
||||
T *getTypePtr() const { return cast_or_null<T>(Stored.getTypePtr()); }
|
||||
|
||||
/// \brief Implicit conversion to a qualified type.
|
||||
operator QualType() const { return Stored; }
|
||||
|
||||
/// \brief Retrieve a canonical type pointer with a different static type,
|
||||
/// upcasting or downcasting as needed.
|
||||
///
|
||||
/// The getAs() function is typically used to try to downcast to a
|
||||
/// more specific (canonical) type in the type system. For example:
|
||||
///
|
||||
/// @code
|
||||
/// void f(CanQual<Type> T) {
|
||||
/// if (CanQual<PointerType> Ptr = T->getAs<PointerType>()) {
|
||||
/// // look at Ptr's pointee type
|
||||
/// }
|
||||
/// }
|
||||
/// @endcode
|
||||
///
|
||||
/// \returns A proxy pointer to the same type, but with the specified
|
||||
/// static type (@p U). If the dynamic type is not the specified static type
|
||||
/// or a derived class thereof, a NULL canonical type.
|
||||
template<typename U> CanProxy<U> getAs() const;
|
||||
|
||||
/// \brief Overloaded arrow operator that produces a canonical type
|
||||
/// proxy.
|
||||
CanProxy<T> operator->() const;
|
||||
|
||||
/// \brief Retrieve the const/volatile/restrict qualifiers.
|
||||
unsigned getCVRQualifiers() const { return Stored.getCVRQualifiers(); }
|
||||
|
||||
/// \brief Set the const/volatile/restrict qualifiers
|
||||
void setCVRQualifiers(unsigned Quals) { Stored.setCVRQualifiers(Quals); }
|
||||
|
||||
bool isConstQualified() const {
|
||||
return (getCVRQualifiers() & QualType::Const) ? true : false;
|
||||
}
|
||||
bool isVolatileQualified() const {
|
||||
return (getCVRQualifiers() & QualType::Volatile) ? true : false;
|
||||
}
|
||||
bool isRestrictQualified() const {
|
||||
return (getCVRQualifiers() & QualType::Restrict) ? true : false;
|
||||
}
|
||||
|
||||
/// \brief Retrieve the unqualified form of this type.
|
||||
CanQual<T> getUnqualifiedType() const;
|
||||
|
||||
CanQual<T> getQualifiedType(unsigned TQs) const {
|
||||
return CanQual<T>::CreateUnsafe(QualType(getTypePtr(), TQs));
|
||||
}
|
||||
|
||||
/// \brief Determines whether this canonical type is more qualified than
|
||||
/// the @p Other canonical type.
|
||||
bool isMoreQualifiedThan(CanQual<T> Other) const {
|
||||
return Stored.isMoreQualifiedThan(Other.Stored);
|
||||
}
|
||||
|
||||
/// \brief Determines whether this canonical type is at least as qualified as
|
||||
/// the @p Other canonical type.
|
||||
bool isAtLeastAsQualifiedAs(CanQual<T> Other) const {
|
||||
return Stored.isAtLeastAsQualifiedAs(Other.Stored);
|
||||
}
|
||||
|
||||
/// \brief If the canonical type is a reference type, returns the type that
|
||||
/// it refers to; otherwise,
|
||||
CanQual<Type> getNonReferenceType() const;
|
||||
|
||||
/// \brief Retrieve the internal representation of this canonical type.
|
||||
void *getAsOpaquePtr() const { return Stored.getAsOpaquePtr(); }
|
||||
|
||||
/// \brief Construct a canonical type from its internal representation.
|
||||
static CanQual<T> getFromOpaquePtr(void *Ptr);
|
||||
|
||||
/// \brief Builds a canonical type from a QualType.
|
||||
///
|
||||
/// This routine is inherently unsafe, because it requires the user to
|
||||
/// ensure that the given type is a canonical type with the correct
|
||||
// (dynamic) type.
|
||||
static CanQual<T> CreateUnsafe(QualType Other);
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
inline bool operator==(CanQual<T> x, CanQual<U> y) {
|
||||
return x.getAsOpaquePtr() == y.getAsOpaquePtr();
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
inline bool operator!=(CanQual<T> x, CanQual<U> y) {
|
||||
return x.getAsOpaquePtr() != y.getAsOpaquePtr();
|
||||
}
|
||||
|
||||
/// \brief Represents a canonical, potentially-qualified type.
|
||||
typedef CanQual<Type> CanQualType;
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// Internal proxy classes used by canonical types
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#define LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(Accessor) \
|
||||
CanQualType Accessor() const { \
|
||||
return CanQualType::CreateUnsafe(this->getTypePtr()->Accessor()); \
|
||||
}
|
||||
|
||||
#define LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Type, Accessor) \
|
||||
Type Accessor() const { return this->getTypePtr()->Accessor(); }
|
||||
|
||||
/// \brief Base class of all canonical proxy types, which is responsible for
|
||||
/// storing the underlying canonical type and providing basic conversions.
|
||||
template<typename T>
|
||||
class CanProxyBase {
|
||||
protected:
|
||||
CanQual<T> Stored;
|
||||
|
||||
public:
|
||||
/// \brief Retrieve the pointer to the underlying Type
|
||||
T* getTypePtr() const { return Stored.getTypePtr(); }
|
||||
|
||||
/// \brief Implicit conversion to the underlying pointer.
|
||||
///
|
||||
/// Also provides the ability to use canonical type proxies in a Boolean
|
||||
// context,e.g.,
|
||||
/// @code
|
||||
/// if (CanQual<PointerType> Ptr = T->getAs<PointerType>()) { ... }
|
||||
/// @endcode
|
||||
operator const T*() const { return this->Stored.getTypePtr(); }
|
||||
|
||||
/// \brief Try to convert the given canonical type to a specific structural
|
||||
/// type.
|
||||
template<typename U> CanProxy<U> getAs() const {
|
||||
return this->Stored.template getAs<U>();
|
||||
}
|
||||
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Type::TypeClass, getTypeClass)
|
||||
|
||||
// Type predicates
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjectType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIncompleteType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIncompleteOrObjectType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isPODType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariablyModifiedType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegerType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isEnumeralType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBooleanType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isCharType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isWideCharType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegralType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isRealFloatingType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isComplexType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAnyComplexType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isFloatingType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isRealType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isArithmeticType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVoidType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isDerivedType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isScalarType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAggregateType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAnyPointerType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVoidPointerType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isFunctionPointerType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isMemberFunctionPointerType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isClassType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isStructureType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnionType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isComplexIntegerType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isNullPtrType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isDependentType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isOverloadableType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasPointerRepresentation)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasObjCPointerRepresentation)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isPromotableIntegerType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnsignedIntegerType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isConstantSizeType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSpecifierType)
|
||||
|
||||
/// \brief Retrieve the proxy-adaptor type.
|
||||
///
|
||||
/// This arrow operator is used when CanProxyAdaptor has been specialized
|
||||
/// for the given type T. In that case, we reference members of the
|
||||
/// CanProxyAdaptor specialization. Otherwise, this operator will be hidden
|
||||
/// by the arrow operator in the primary CanProxyAdaptor template.
|
||||
const CanProxyAdaptor<T> *operator->() const {
|
||||
return static_cast<const CanProxyAdaptor<T> *>(this);
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Replacable canonical proxy adaptor class that provides the link
|
||||
/// between a canonical type and the accessors of the type.
|
||||
///
|
||||
/// The CanProxyAdaptor is a replaceable class template that is instantiated
|
||||
/// as part of each canonical proxy type. The primary template merely provides
|
||||
/// redirection to the underlying type (T), e.g., @c PointerType. One can
|
||||
/// provide specializations of this class template for each underlying type
|
||||
/// that provide accessors returning canonical types (@c CanQualType) rather
|
||||
/// than the more typical @c QualType, to propagate the notion of "canonical"
|
||||
/// through the system.
|
||||
template<typename T>
|
||||
struct CanProxyAdaptor : CanProxyBase<T> { };
|
||||
|
||||
/// \brief Canonical proxy type returned when retrieving the members of a
|
||||
/// canonical type or as the result of the @c CanQual<T>::getAs member
|
||||
/// function.
|
||||
///
|
||||
/// The CanProxy type mainly exists as a proxy through which operator-> will
|
||||
/// look to either map down to a raw T* (e.g., PointerType*) or to a proxy
|
||||
/// type that provides canonical-type access to the fields of the type.
|
||||
template<typename T>
|
||||
class CanProxy : public CanProxyAdaptor<T> {
|
||||
public:
|
||||
/// \brief Build a NULL proxy.
|
||||
CanProxy() { }
|
||||
|
||||
/// \brief Build a proxy to the given canonical type.
|
||||
CanProxy(CanQual<T> Stored) { this->Stored = Stored; }
|
||||
|
||||
/// \brief Implicit conversion to the stored canonical type.
|
||||
operator CanQual<T>() const { return this->Stored; }
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// Implement simplify_type for CanQual<T>, so that we can dyn_cast from
|
||||
/// CanQual<T> to a specific Type class. We're prefer isa/dyn_cast/cast/etc.
|
||||
/// to return smart pointer (proxies?).
|
||||
template<typename T>
|
||||
struct simplify_type<const ::clang::CanQual<T> > {
|
||||
typedef T* SimpleType;
|
||||
static SimpleType getSimplifiedValue(const ::clang::CanQual<T> &Val) {
|
||||
return Val.getTypePtr();
|
||||
}
|
||||
};
|
||||
template<typename T>
|
||||
struct simplify_type< ::clang::CanQual<T> >
|
||||
: public simplify_type<const ::clang::CanQual<T> > {};
|
||||
|
||||
// Teach SmallPtrSet that CanQual<T> is "basically a pointer".
|
||||
template<typename T>
|
||||
class PointerLikeTypeTraits<clang::CanQual<T> > {
|
||||
public:
|
||||
static inline void *getAsVoidPointer(clang::CanQual<T> P) {
|
||||
return P.getAsOpaquePtr();
|
||||
}
|
||||
static inline clang::CanQual<T> getFromVoidPointer(void *P) {
|
||||
return clang::CanQual<T>::getFromOpaquePtr(P);
|
||||
}
|
||||
// CVR qualifiers go in low bits.
|
||||
enum { NumLowBitsAvailable = 0 };
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
namespace clang {
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// Canonical proxy adaptors for canonical type nodes.
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
/// \brief Iterator adaptor that turns an iterator over canonical QualTypes
|
||||
/// into an iterator over CanQualTypes.
|
||||
template<typename InputIterator>
|
||||
class CanTypeIterator {
|
||||
InputIterator Iter;
|
||||
|
||||
public:
|
||||
typedef CanQualType value_type;
|
||||
typedef value_type reference;
|
||||
typedef CanProxy<Type> pointer;
|
||||
typedef typename std::iterator_traits<InputIterator>::difference_type
|
||||
difference_type;
|
||||
typedef typename std::iterator_traits<InputIterator>::iterator_category
|
||||
iterator_category;
|
||||
|
||||
CanTypeIterator() : Iter() { }
|
||||
explicit CanTypeIterator(InputIterator Iter) : Iter(Iter) { }
|
||||
|
||||
// Input iterator
|
||||
reference operator*() const {
|
||||
return CanQualType::CreateUnsafe(*Iter);
|
||||
}
|
||||
|
||||
pointer operator->() const;
|
||||
|
||||
CanTypeIterator &operator++() {
|
||||
++Iter;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CanTypeIterator operator++(int) {
|
||||
CanTypeIterator Tmp(*this);
|
||||
++Iter;
|
||||
return Tmp;
|
||||
}
|
||||
|
||||
friend bool operator==(const CanTypeIterator& X, const CanTypeIterator &Y) {
|
||||
return X.Iter == Y.Iter;
|
||||
}
|
||||
friend bool operator!=(const CanTypeIterator& X, const CanTypeIterator &Y) {
|
||||
return X.Iter != Y.Iter;
|
||||
}
|
||||
|
||||
// Bidirectional iterator
|
||||
CanTypeIterator &operator--() {
|
||||
--Iter;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CanTypeIterator operator--(int) {
|
||||
CanTypeIterator Tmp(*this);
|
||||
--Iter;
|
||||
return Tmp;
|
||||
}
|
||||
|
||||
// Random access iterator
|
||||
reference operator[](difference_type n) const {
|
||||
return CanQualType::CreateUnsafe(Iter[n]);
|
||||
}
|
||||
|
||||
CanTypeIterator &operator+=(difference_type n) {
|
||||
Iter += n;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CanTypeIterator &operator-=(difference_type n) {
|
||||
Iter -= n;
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend CanTypeIterator operator+(CanTypeIterator X, difference_type n) {
|
||||
X += n;
|
||||
return X;
|
||||
}
|
||||
|
||||
friend CanTypeIterator operator+(difference_type n, CanTypeIterator X) {
|
||||
X += n;
|
||||
return X;
|
||||
}
|
||||
|
||||
friend CanTypeIterator operator-(CanTypeIterator X, difference_type n) {
|
||||
X -= n;
|
||||
return X;
|
||||
}
|
||||
|
||||
friend difference_type operator-(const CanTypeIterator &X,
|
||||
const CanTypeIterator &Y) {
|
||||
return X - Y;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<ExtQualType> : public CanProxyBase<ExtQualType> {
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Type*, getBaseType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(QualType::GCAttrTypes, getObjCGCAttr)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getAddressSpace)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<ComplexType> : public CanProxyBase<ComplexType> {
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<PointerType> : public CanProxyBase<PointerType> {
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<BlockPointerType>
|
||||
: public CanProxyBase<BlockPointerType>
|
||||
{
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<ReferenceType> : public CanProxyBase<ReferenceType> {
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<LValueReferenceType>
|
||||
: public CanProxyBase<LValueReferenceType>
|
||||
{
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<RValueReferenceType>
|
||||
: public CanProxyBase<RValueReferenceType>
|
||||
{
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<MemberPointerType>
|
||||
: public CanProxyBase<MemberPointerType>
|
||||
{
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const Type *, getClass)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<ArrayType> : public CanProxyBase<ArrayType> {
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier,
|
||||
getSizeModifier)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getIndexTypeQualifier)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<ConstantArrayType>
|
||||
: public CanProxyBase<ConstantArrayType>
|
||||
{
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier,
|
||||
getSizeModifier)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getIndexTypeQualifier)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const llvm::APInt &, getSize)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<ConstantArrayWithExprType>
|
||||
: public CanProxyBase<ConstantArrayWithExprType>
|
||||
{
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier,
|
||||
getSizeModifier)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getIndexTypeQualifier)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const llvm::APInt &, getSize)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Expr *, getSizeExpr)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceRange, getBracketsRange)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getLBracketLoc)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getRBracketLoc)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<ConstantArrayWithoutExprType>
|
||||
: public CanProxyBase<ConstantArrayWithoutExprType>
|
||||
{
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier,
|
||||
getSizeModifier)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getIndexTypeQualifier)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const llvm::APInt &, getSize)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<IncompleteArrayType>
|
||||
: public CanProxyBase<IncompleteArrayType>
|
||||
{
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier,
|
||||
getSizeModifier)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getIndexTypeQualifier)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<VariableArrayType>
|
||||
: public CanProxyBase<VariableArrayType>
|
||||
{
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier,
|
||||
getSizeModifier)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getIndexTypeQualifier)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Expr *, getSizeExpr)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceRange, getBracketsRange)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getLBracketLoc)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getRBracketLoc)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<DependentSizedArrayType>
|
||||
: public CanProxyBase<DependentSizedArrayType>
|
||||
{
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Expr *, getSizeExpr)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceRange, getBracketsRange)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getLBracketLoc)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getRBracketLoc)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<DependentSizedExtVectorType>
|
||||
: public CanProxyBase<DependentSizedExtVectorType>
|
||||
{
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const Expr *, getSizeExpr)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getAttributeLoc)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<VectorType> : public CanProxyBase<VectorType> {
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumElements)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<ExtVectorType> : public CanProxyBase<ExtVectorType> {
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumElements)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<FunctionType> : public CanProxyBase<FunctionType> {
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<FunctionNoProtoType>
|
||||
: public CanProxyBase<FunctionNoProtoType>
|
||||
{
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<FunctionProtoType>
|
||||
: public CanProxyBase<FunctionProtoType>
|
||||
{
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumArgs);
|
||||
CanQualType getArgType(unsigned i) const {
|
||||
return CanQualType::CreateUnsafe(this->getTypePtr()->getArgType(i));
|
||||
}
|
||||
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariadic)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getTypeQuals)
|
||||
|
||||
typedef CanTypeIterator<FunctionProtoType::arg_type_iterator>
|
||||
arg_type_iterator;
|
||||
|
||||
arg_type_iterator arg_type_begin() const {
|
||||
return arg_type_iterator(this->getTypePtr()->arg_type_begin());
|
||||
}
|
||||
|
||||
arg_type_iterator arg_type_end() const {
|
||||
return arg_type_iterator(this->getTypePtr()->arg_type_end());
|
||||
}
|
||||
|
||||
// Note: canonical function types never have exception specifications
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<TypeOfType> : public CanProxyBase<TypeOfType> {
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<DecltypeType> : public CanProxyBase<DecltypeType> {
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Expr *, getUnderlyingExpr)
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<TagType> : public CanProxyBase<TagType> {
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(TagDecl *, getDecl)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<RecordType> : public CanProxyBase<RecordType> {
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(RecordDecl *, getDecl)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasConstFields)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getAddressSpace)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<EnumType> : public CanProxyBase<EnumType> {
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(EnumDecl *, getDecl)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<TemplateTypeParmType>
|
||||
: public CanProxyBase<TemplateTypeParmType>
|
||||
{
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getDepth)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getIndex)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isParameterPack)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(IdentifierInfo *, getName)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<ObjCObjectPointerType>
|
||||
: public CanProxyBase<ObjCObjectPointerType>
|
||||
{
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const ObjCInterfaceType *,
|
||||
getInterfaceType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCIdType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCClassType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedIdType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedClassType)
|
||||
|
||||
typedef ObjCObjectPointerType::qual_iterator qual_iterator;
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_begin)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_end)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, qual_empty)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumProtocols)
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// Method and function definitions
|
||||
//----------------------------------------------------------------------------//
|
||||
template<typename T>
|
||||
inline CanQual<T> CanQual<T>::getUnqualifiedType() const {
|
||||
if (CanQual<ExtQualType> EQ = getAs<ExtQualType>())
|
||||
return CanQual<T>::CreateUnsafe(QualType(EQ->getBaseType(), 0));
|
||||
return CanQual<T>::CreateUnsafe(QualType(Stored.getTypePtr(), 0));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline CanQual<Type> CanQual<T>::getNonReferenceType() const {
|
||||
if (CanQual<ReferenceType> RefType = getAs<ReferenceType>())
|
||||
return RefType->getPointeeType();
|
||||
else
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
CanQual<T> CanQual<T>::getFromOpaquePtr(void *Ptr) {
|
||||
CanQual<T> Result;
|
||||
Result.Stored.setFromOpaqueValue(Ptr);
|
||||
assert((!Result || Result.Stored.isCanonical())
|
||||
&& "Type is not canonical!");
|
||||
return Result;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
CanQual<T> CanQual<T>::CreateUnsafe(QualType Other) {
|
||||
assert((Other.isNull() || Other->isCanonical()) && "Type is not canonical!");
|
||||
assert((Other.isNull() || isa<T>(Other.getTypePtr())) &&
|
||||
"Dynamic type does not meet the static type's requires");
|
||||
CanQual<T> Result;
|
||||
Result.Stored = Other;
|
||||
return Result;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
CanProxy<U> CanQual<T>::getAs() const {
|
||||
if (Stored.isNull())
|
||||
return CanProxy<U>();
|
||||
|
||||
if (isa<U>(Stored.getTypePtr()))
|
||||
return CanQual<U>::CreateUnsafe(Stored);
|
||||
|
||||
if (const ExtQualType *EQ = Stored->getAs<ExtQualType>())
|
||||
return CanQual<T>::CreateUnsafe(QualType(EQ->getBaseType(), 0))
|
||||
.template getAs<U>();
|
||||
|
||||
return CanProxy<U>();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
CanProxy<T> CanQual<T>::operator->() const {
|
||||
return CanProxy<T>(*this);
|
||||
}
|
||||
|
||||
template<typename InputIterator>
|
||||
typename CanTypeIterator<InputIterator>::pointer
|
||||
CanTypeIterator<InputIterator>::operator->() const {
|
||||
return CanProxy<Type>(*this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // LLVM_CLANG_AST_CANONICAL_TYPE_H
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
#include "clang/Basic/IdentifierTable.h"
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/AST/CanonicalType.h"
|
||||
|
||||
namespace llvm {
|
||||
template <typename T> struct DenseMapInfo;
|
||||
@@ -290,19 +291,19 @@ public:
|
||||
|
||||
/// getCXXConstructorName - Returns the name of a C++ constructor
|
||||
/// for the given Type.
|
||||
DeclarationName getCXXConstructorName(QualType Ty) {
|
||||
DeclarationName getCXXConstructorName(CanQualType Ty) {
|
||||
return getCXXSpecialName(DeclarationName::CXXConstructorName, Ty);
|
||||
}
|
||||
|
||||
/// getCXXDestructorName - Returns the name of a C++ destructor
|
||||
/// for the given Type.
|
||||
DeclarationName getCXXDestructorName(QualType Ty) {
|
||||
DeclarationName getCXXDestructorName(CanQualType Ty) {
|
||||
return getCXXSpecialName(DeclarationName::CXXDestructorName, Ty);
|
||||
}
|
||||
|
||||
/// getCXXConversionFunctionName - Returns the name of a C++
|
||||
/// conversion function for the given Type.
|
||||
DeclarationName getCXXConversionFunctionName(QualType Ty) {
|
||||
DeclarationName getCXXConversionFunctionName(CanQualType Ty) {
|
||||
return getCXXSpecialName(DeclarationName::CXXConversionFunctionName, Ty);
|
||||
}
|
||||
|
||||
@@ -310,7 +311,7 @@ public:
|
||||
/// of C++ name, e.g., for a constructor, destructor, or conversion
|
||||
/// function.
|
||||
DeclarationName getCXXSpecialName(DeclarationName::NameKind Kind,
|
||||
QualType Ty);
|
||||
CanQualType Ty);
|
||||
|
||||
/// getCXXOperatorName - Get the name of the overloadable C++
|
||||
/// operator corresponding to Op.
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "clang/AST/NestedNameSpecifier.h"
|
||||
#include "clang/AST/TemplateName.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/type_traits.h"
|
||||
#include "llvm/ADT/APSInt.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/ADT/PointerIntPair.h"
|
||||
@@ -178,11 +179,11 @@ public:
|
||||
|
||||
/// operator==/!= - Indicate whether the specified types and qualifiers are
|
||||
/// identical.
|
||||
bool operator==(const QualType &RHS) const {
|
||||
return Value == RHS.Value;
|
||||
friend bool operator==(const QualType &LHS, const QualType &RHS) {
|
||||
return LHS.Value == RHS.Value;
|
||||
}
|
||||
bool operator!=(const QualType &RHS) const {
|
||||
return Value != RHS.Value;
|
||||
friend bool operator!=(const QualType &LHS, const QualType &RHS) {
|
||||
return LHS.Value != RHS.Value;
|
||||
}
|
||||
std::string getAsString() const;
|
||||
|
||||
@@ -251,6 +252,7 @@ public:
|
||||
// CVR qualifiers go in low bits.
|
||||
enum { NumLowBitsAvailable = 0 };
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
namespace clang {
|
||||
|
||||
@@ -2070,18 +2070,19 @@ QualType ASTContext::getPointerDiffType() const {
|
||||
/// include typedefs, 'typeof' operators, etc. The returned type is guaranteed
|
||||
/// to be free of any of these, allowing two canonical types to be compared
|
||||
/// for exact equality with a simple pointer comparison.
|
||||
QualType ASTContext::getCanonicalType(QualType T) {
|
||||
CanQualType ASTContext::getCanonicalType(QualType T) {
|
||||
QualType CanType = T.getTypePtr()->getCanonicalTypeInternal();
|
||||
|
||||
// If the result has type qualifiers, make sure to canonicalize them as well.
|
||||
unsigned TypeQuals = T.getCVRQualifiers() | CanType.getCVRQualifiers();
|
||||
if (TypeQuals == 0) return CanType;
|
||||
if (TypeQuals == 0)
|
||||
return CanQualType::CreateUnsafe(CanType);
|
||||
|
||||
// If the type qualifiers are on an array type, get the canonical type of the
|
||||
// array with the qualifiers applied to the element type.
|
||||
ArrayType *AT = dyn_cast<ArrayType>(CanType);
|
||||
if (!AT)
|
||||
return CanType.getQualifiedType(TypeQuals);
|
||||
return CanQualType::CreateUnsafe(CanType.getQualifiedType(TypeQuals));
|
||||
|
||||
// Get the canonical version of the element with the extra qualifiers on it.
|
||||
// This can recursively sink qualifiers through multiple levels of arrays.
|
||||
@@ -2089,25 +2090,29 @@ QualType ASTContext::getCanonicalType(QualType T) {
|
||||
NewEltTy = getCanonicalType(NewEltTy);
|
||||
|
||||
if (ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT))
|
||||
return getConstantArrayType(NewEltTy, CAT->getSize(),CAT->getSizeModifier(),
|
||||
CAT->getIndexTypeQualifier());
|
||||
return CanQualType::CreateUnsafe(
|
||||
getConstantArrayType(NewEltTy, CAT->getSize(),
|
||||
CAT->getSizeModifier(),
|
||||
CAT->getIndexTypeQualifier()));
|
||||
if (IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(AT))
|
||||
return getIncompleteArrayType(NewEltTy, IAT->getSizeModifier(),
|
||||
IAT->getIndexTypeQualifier());
|
||||
return CanQualType::CreateUnsafe(
|
||||
getIncompleteArrayType(NewEltTy, IAT->getSizeModifier(),
|
||||
IAT->getIndexTypeQualifier()));
|
||||
|
||||
if (DependentSizedArrayType *DSAT = dyn_cast<DependentSizedArrayType>(AT))
|
||||
return getDependentSizedArrayType(NewEltTy,
|
||||
DSAT->getSizeExpr(),
|
||||
DSAT->getSizeModifier(),
|
||||
DSAT->getIndexTypeQualifier(),
|
||||
DSAT->getBracketsRange());
|
||||
return CanQualType::CreateUnsafe(
|
||||
getDependentSizedArrayType(NewEltTy,
|
||||
DSAT->getSizeExpr(),
|
||||
DSAT->getSizeModifier(),
|
||||
DSAT->getIndexTypeQualifier(),
|
||||
DSAT->getBracketsRange()));
|
||||
|
||||
VariableArrayType *VAT = cast<VariableArrayType>(AT);
|
||||
return getVariableArrayType(NewEltTy,
|
||||
VAT->getSizeExpr(),
|
||||
VAT->getSizeModifier(),
|
||||
VAT->getIndexTypeQualifier(),
|
||||
VAT->getBracketsRange());
|
||||
return CanQualType::CreateUnsafe(getVariableArrayType(NewEltTy,
|
||||
VAT->getSizeExpr(),
|
||||
VAT->getSizeModifier(),
|
||||
VAT->getIndexTypeQualifier(),
|
||||
VAT->getBracketsRange()));
|
||||
}
|
||||
|
||||
TemplateName ASTContext::getCanonicalTemplateName(TemplateName Name) {
|
||||
@@ -2250,7 +2255,7 @@ const ArrayType *ASTContext::getAsArrayType(QualType T) {
|
||||
|
||||
// If we get here, we either have type qualifiers on the type, or we have
|
||||
// sugar such as a typedef in the way. If we have type qualifiers on the type
|
||||
// we must propagate them down into the elemeng type.
|
||||
// we must propagate them down into the element type.
|
||||
unsigned CVRQuals = T.getCVRQualifiers();
|
||||
unsigned AddrSpace = 0;
|
||||
Type *Ty = T.getTypePtr();
|
||||
|
||||
@@ -304,7 +304,8 @@ CXXRecordDecl::getDestructor(ASTContext &Context) {
|
||||
QualType ClassType = Context.getTypeDeclType(this);
|
||||
|
||||
DeclarationName Name
|
||||
= Context.DeclarationNames.getCXXDestructorName(ClassType);
|
||||
= Context.DeclarationNames.getCXXDestructorName(
|
||||
Context.getCanonicalType(ClassType));
|
||||
|
||||
DeclContext::lookup_iterator I, E;
|
||||
llvm::tie(I, E) = lookup(Name);
|
||||
|
||||
@@ -298,12 +298,10 @@ DeclarationNameTable::~DeclarationNameTable() {
|
||||
|
||||
DeclarationName
|
||||
DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind,
|
||||
QualType Ty) {
|
||||
CanQualType Ty) {
|
||||
assert(Kind >= DeclarationName::CXXConstructorName &&
|
||||
Kind <= DeclarationName::CXXConversionFunctionName &&
|
||||
"Kind must be a C++ special name kind");
|
||||
assert(Ty->isCanonical() &&
|
||||
"Can only build C++ special names from canonical types");
|
||||
llvm::FoldingSet<CXXSpecialName> *SpecialNames
|
||||
= static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
|
||||
|
||||
|
||||
@@ -2380,15 +2380,15 @@ PCHReader::ReadDeclarationName(const RecordData &Record, unsigned &Idx) {
|
||||
|
||||
case DeclarationName::CXXConstructorName:
|
||||
return Context->DeclarationNames.getCXXConstructorName(
|
||||
GetType(Record[Idx++]));
|
||||
Context->getCanonicalType(GetType(Record[Idx++])));
|
||||
|
||||
case DeclarationName::CXXDestructorName:
|
||||
return Context->DeclarationNames.getCXXDestructorName(
|
||||
GetType(Record[Idx++]));
|
||||
Context->getCanonicalType(GetType(Record[Idx++])));
|
||||
|
||||
case DeclarationName::CXXConversionFunctionName:
|
||||
return Context->DeclarationNames.getCXXConversionFunctionName(
|
||||
GetType(Record[Idx++]));
|
||||
Context->getCanonicalType(GetType(Record[Idx++])));
|
||||
|
||||
case DeclarationName::CXXOperatorName:
|
||||
return Context->DeclarationNames.getCXXOperatorName(
|
||||
|
||||
@@ -1553,21 +1553,21 @@ DeclarationName Sema::GetNameForDeclarator(Declarator &D) {
|
||||
|
||||
case Declarator::DK_Constructor: {
|
||||
QualType Ty = QualType::getFromOpaquePtr(D.getDeclaratorIdType());
|
||||
Ty = Context.getCanonicalType(Ty);
|
||||
return Context.DeclarationNames.getCXXConstructorName(Ty);
|
||||
return Context.DeclarationNames.getCXXConstructorName(
|
||||
Context.getCanonicalType(Ty));
|
||||
}
|
||||
|
||||
case Declarator::DK_Destructor: {
|
||||
QualType Ty = QualType::getFromOpaquePtr(D.getDeclaratorIdType());
|
||||
Ty = Context.getCanonicalType(Ty);
|
||||
return Context.DeclarationNames.getCXXDestructorName(Ty);
|
||||
return Context.DeclarationNames.getCXXDestructorName(
|
||||
Context.getCanonicalType(Ty));
|
||||
}
|
||||
|
||||
case Declarator::DK_Conversion: {
|
||||
// FIXME: We'd like to keep the non-canonical type for diagnostics!
|
||||
QualType Ty = QualType::getFromOpaquePtr(D.getDeclaratorIdType());
|
||||
Ty = Context.getCanonicalType(Ty);
|
||||
return Context.DeclarationNames.getCXXConversionFunctionName(Ty);
|
||||
return Context.DeclarationNames.getCXXConversionFunctionName(
|
||||
Context.getCanonicalType(Ty));
|
||||
}
|
||||
|
||||
case Declarator::DK_Operator:
|
||||
@@ -2736,9 +2736,9 @@ void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
|
||||
CXXRecordDecl *Record = cast<CXXRecordDecl>(NewFD->getParent());
|
||||
QualType ClassType = Context.getTypeDeclType(Record);
|
||||
if (!ClassType->isDependentType()) {
|
||||
ClassType = Context.getCanonicalType(ClassType);
|
||||
DeclarationName Name
|
||||
= Context.DeclarationNames.getCXXDestructorName(ClassType);
|
||||
= Context.DeclarationNames.getCXXDestructorName(
|
||||
Context.getCanonicalType(ClassType));
|
||||
if (NewFD->getDeclName() != Name) {
|
||||
Diag(NewFD->getLocation(), diag::err_destructor_name);
|
||||
return NewFD->setInvalidDecl();
|
||||
|
||||
@@ -1259,8 +1259,8 @@ void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
|
||||
/// [special]p1). This routine can only be executed just before the
|
||||
/// definition of the class is complete.
|
||||
void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
|
||||
QualType ClassType = Context.getTypeDeclType(ClassDecl);
|
||||
ClassType = Context.getCanonicalType(ClassType);
|
||||
CanQualType ClassType
|
||||
= Context.getCanonicalType(Context.getTypeDeclType(ClassDecl));
|
||||
|
||||
// FIXME: Implicit declarations have exception specifications, which are
|
||||
// the union of the specifications of the implicitly called functions.
|
||||
|
||||
@@ -32,7 +32,7 @@ Sema::ActOnCXXConversionFunctionExpr(Scope *S, SourceLocation OperatorLoc,
|
||||
const CXXScopeSpec &SS,
|
||||
bool isAddressOfOperand) {
|
||||
QualType ConvType = QualType::getFromOpaquePtr(Ty);
|
||||
QualType ConvTypeCanon = Context.getCanonicalType(ConvType);
|
||||
CanQualType ConvTypeCanon = Context.getCanonicalType(ConvType);
|
||||
DeclarationName ConvName
|
||||
= Context.DeclarationNames.getCXXConversionFunctionName(ConvTypeCanon);
|
||||
return ActOnDeclarationNameExpr(S, OperatorLoc, ConvName, HasTrailingLParen,
|
||||
|
||||
@@ -484,7 +484,7 @@ Decl *TemplateDeclInstantiator::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
|
||||
|
||||
// Build the instantiated destructor declaration.
|
||||
CXXRecordDecl *Record = cast<CXXRecordDecl>(Owner);
|
||||
QualType ClassTy =
|
||||
CanQualType ClassTy =
|
||||
SemaRef.Context.getCanonicalType(SemaRef.Context.getTypeDeclType(Record));
|
||||
CXXDestructorDecl *Destructor
|
||||
= CXXDestructorDecl::Create(SemaRef.Context, Record,
|
||||
@@ -517,7 +517,7 @@ Decl *TemplateDeclInstantiator::VisitCXXConversionDecl(CXXConversionDecl *D) {
|
||||
// Build the instantiated conversion declaration.
|
||||
CXXRecordDecl *Record = cast<CXXRecordDecl>(Owner);
|
||||
QualType ClassTy = SemaRef.Context.getTypeDeclType(Record);
|
||||
QualType ConvTy
|
||||
CanQualType ConvTy
|
||||
= SemaRef.Context.getCanonicalType(T->getAsFunctionType()->getResultType());
|
||||
CXXConversionDecl *Conversion
|
||||
= CXXConversionDecl::Create(SemaRef.Context, Record,
|
||||
|
||||
Reference in New Issue
Block a user