Teach Type::getAs<TemplateSpecializationType> that a TemplateSpecializationType
for a type alias template can appear as sugar at any level of desugaring, just like a TypedefType. llvm-svn: 164655
This commit is contained in:
parent
a398d4cfaf
commit
6e0605d654
|
@ -1804,6 +1804,11 @@ public:
|
|||
/// until it reaches a TypedefType or a non-sugared type.
|
||||
template <> const TypedefType *Type::getAs() const;
|
||||
|
||||
/// \brief This will check for a TemplateSpecializationType by removing any
|
||||
/// existing sugar until it reaches a TemplateSpecializationType or a
|
||||
/// non-sugared type.
|
||||
template <> const TemplateSpecializationType *Type::getAs() const;
|
||||
|
||||
// We can do canonical leaf types faster, because we don't have to
|
||||
// worry about preserving child type decoration.
|
||||
#define TYPE(Class, Base)
|
||||
|
|
|
@ -288,18 +288,17 @@ QualType QualType::IgnoreParens(QualType T) {
|
|||
return T;
|
||||
}
|
||||
|
||||
/// \brief This will check for a TypedefType by removing any existing sugar
|
||||
/// until it reaches a TypedefType or a non-sugared type.
|
||||
template <> const TypedefType *Type::getAs() const {
|
||||
const Type *Cur = this;
|
||||
|
||||
/// \brief This will check for a T (which should be a Type which can act as
|
||||
/// sugar, such as a TypedefType) by removing any existing sugar until it
|
||||
/// reaches a T or a non-sugared type.
|
||||
template<typename T> static const T *getAsSugar(const Type *Cur) {
|
||||
while (true) {
|
||||
if (const TypedefType *TDT = dyn_cast<TypedefType>(Cur))
|
||||
return TDT;
|
||||
if (const T *Sugar = dyn_cast<T>(Cur))
|
||||
return Sugar;
|
||||
switch (Cur->getTypeClass()) {
|
||||
#define ABSTRACT_TYPE(Class, Parent)
|
||||
#define TYPE(Class, Parent) \
|
||||
case Class: { \
|
||||
case Type::Class: { \
|
||||
const Class##Type *Ty = cast<Class##Type>(Cur); \
|
||||
if (!Ty->isSugared()) return 0; \
|
||||
Cur = Ty->desugar().getTypePtr(); \
|
||||
|
@ -310,6 +309,14 @@ template <> const TypedefType *Type::getAs() const {
|
|||
}
|
||||
}
|
||||
|
||||
template <> const TypedefType *Type::getAs() const {
|
||||
return getAsSugar<TypedefType>(this);
|
||||
}
|
||||
|
||||
template <> const TemplateSpecializationType *Type::getAs() const {
|
||||
return getAsSugar<TemplateSpecializationType>(this);
|
||||
}
|
||||
|
||||
/// getUnqualifiedDesugaredType - Pull any qualifiers and syntactic
|
||||
/// sugar off the given type. This should produce an object of the
|
||||
/// same dynamic type as the canonical type.
|
||||
|
|
|
@ -95,13 +95,17 @@ template<unsigned N, typename...Ts> struct drop {
|
|||
};
|
||||
|
||||
using T1 = take<3, int, char, double, long>::type; // expected-note {{previous}}
|
||||
using T1 = types<void, void, void, void>; // expected-error {{'types<void, void, void, void>' vs 'types<int, char, double, (no argument)>'}}
|
||||
// FIXME: Desguar the types on the RHS in this diagnostic.
|
||||
// desired-error {{'types<void, void, void, void>' vs 'types<int, char, double, (no argument)>'}}
|
||||
using T1 = types<void, void, void, void>; // expected-error {{'types<void, void, void, void>' vs 'types<typename inner<_>::type, typename inner<_>::type, typename inner<_>::type, (no argument)>'}}
|
||||
using D1 = drop<3, int, char, double, long>::type;
|
||||
using D1 = types<long>;
|
||||
|
||||
using T2 = take<4, int, char, double, long>::type; // expected-note {{previous}}
|
||||
using T2 = types<int, char, double, long>;
|
||||
using T2 = types<void, void, void, void>; // expected-error {{'types<void, void, void, void>' vs 'types<int, char, double, long>'}}
|
||||
// FIXME: Desguar the types on the RHS in this diagnostic.
|
||||
// desired-error {{'types<void, void, void, void>' vs 'types<int, char, double, long>'}}
|
||||
using T2 = types<void, void, void, void>; // expected-error {{'types<void, void, void, void>' vs 'types<typename inner<_>::type, typename inner<_>::type, typename inner<_>::type, typename inner<_>::type>'}}
|
||||
using D2 = drop<4, int, char, double, long>::type;
|
||||
using D2 = types<>;
|
||||
|
||||
|
|
|
@ -426,6 +426,24 @@ void test13() {
|
|||
// CHECK-NOELIDE-TREE: &b13,
|
||||
// CHECK-NOELIDE-TREE: [&d13 != (no argument)]>
|
||||
|
||||
template<typename T> struct s14 {};
|
||||
template<typename T> using a14 = s14<T>;
|
||||
typedef a14<int> b14;
|
||||
template<typename T> using c14 = b14;
|
||||
int f14(c14<int>);
|
||||
int k14 = f14(a14<char>());
|
||||
// CHECK-ELIDE-NOTREE: no matching function for call to 'f14'
|
||||
// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'a14<char>' to 'a14<int>' for 1st argument
|
||||
// CHECK-NOELIDE-NOTREE: no matching function for call to 'f14'
|
||||
// CHECK-NOELIDE-NOTREE: candidate function not viable: no known conversion from 'a14<char>' to 'a14<int>' for 1st argument
|
||||
// CHECK-ELIDE-TREE: no matching function for call to 'f14'
|
||||
// CHECK-ELIDE-TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument
|
||||
// CHECK-ELIDE-TREE: a14<
|
||||
// CHECK-ELIDE-TREE: [char != int]>
|
||||
// CHECK-NOELIDE-TREE: no matching function for call to 'f14'
|
||||
// CHECK-NOELIDE-TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument
|
||||
// CHECK-NOELIDE-TREE: a14<
|
||||
// CHECK-NOELIDE-TREE: [char != int]>
|
||||
|
||||
// CHECK-ELIDE-NOTREE: {{[0-9]*}} errors generated.
|
||||
// CHECK-NOELIDE-NOTREE: {{[0-9]*}} errors generated.
|
||||
|
|
Loading…
Reference in New Issue