diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-09-26 02:18:13 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-09-26 02:18:13 +0000 |
commit | 073819806ba2441e2a3e550107f1e756a6ee3ad0 (patch) | |
tree | 69cd14a4a6a6d78bdc170f2e1f22dacf5b429464 | |
parent | a74b9cd8a6f6d6179713e2eed2d3d9ef8f5f72d1 (diff) |
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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@164655 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/AST/Type.h | 5 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 23 | ||||
-rw-r--r-- | test/CXX/temp/temp.param/p15-cxx0x.cpp | 8 | ||||
-rw-r--r-- | test/Misc/diag-template-diffing.cpp | 18 |
4 files changed, 44 insertions, 10 deletions
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 7811be0e83..8899b50e27 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -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) diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 529c90603c..9db41c4b1e 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -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. diff --git a/test/CXX/temp/temp.param/p15-cxx0x.cpp b/test/CXX/temp/temp.param/p15-cxx0x.cpp index 4cc1f17a11..59618d2636 100644 --- a/test/CXX/temp/temp.param/p15-cxx0x.cpp +++ b/test/CXX/temp/temp.param/p15-cxx0x.cpp @@ -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<>; diff --git a/test/Misc/diag-template-diffing.cpp b/test/Misc/diag-template-diffing.cpp index 9addcc50ae..24563e3ec8 100644 --- a/test/Misc/diag-template-diffing.cpp +++ b/test/Misc/diag-template-diffing.cpp @@ -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. |