aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-09-26 02:18:13 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-09-26 02:18:13 +0000
commit073819806ba2441e2a3e550107f1e756a6ee3ad0 (patch)
tree69cd14a4a6a6d78bdc170f2e1f22dacf5b429464
parenta74b9cd8a6f6d6179713e2eed2d3d9ef8f5f72d1 (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.h5
-rw-r--r--lib/AST/Type.cpp23
-rw-r--r--test/CXX/temp/temp.param/p15-cxx0x.cpp8
-rw-r--r--test/Misc/diag-template-diffing.cpp18
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.