aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Redl <sebastian.redl@getdesigned.at>2010-09-13 22:18:28 +0000
committerSebastian Redl <sebastian.redl@getdesigned.at>2010-09-13 22:18:28 +0000
commit08295a592d7e54e6bea00daeb2abe7ac79a3aaba (patch)
tree1ca02126c224a57c9942f2f0fc0345756773d31c
parent751025d5d174ab75dc3788211581d9fbe6224841 (diff)
Don't crash when using type traits on a class with a constructor template.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@113796 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/SemaExprCXX.cpp8
-rw-r--r--test/SemaCXX/type-traits.cpp11
2 files changed, 19 insertions, 0 deletions
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index b380a4b7a7..e03c5721c6 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -2148,6 +2148,11 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, QualType T) {
DeclContext::lookup_const_iterator Con, ConEnd;
for (llvm::tie(Con, ConEnd) = Self.LookupConstructors(RD);
Con != ConEnd; ++Con) {
+ // A template constructor is never a copy constructor.
+ // FIXME: However, it may actually be selected at the actual overload
+ // resolution point.
+ if (isa<FunctionTemplateDecl>(*Con))
+ continue;
CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
if (Constructor->isCopyConstructor(FoundTQs)) {
FoundConstructor = true;
@@ -2181,6 +2186,9 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, QualType T) {
DeclContext::lookup_const_iterator Con, ConEnd;
for (llvm::tie(Con, ConEnd) = Self.LookupConstructors(RD);
Con != ConEnd; ++Con) {
+ // FIXME: In C++0x, a constructor template can be a default constructor.
+ if (isa<FunctionTemplateDecl>(*Con))
+ continue;
CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
if (Constructor->isDefaultConstructor()) {
const FunctionProtoType *CPT
diff --git a/test/SemaCXX/type-traits.cpp b/test/SemaCXX/type-traits.cpp
index cb88220bb1..d6fccffaac 100644
--- a/test/SemaCXX/type-traits.cpp
+++ b/test/SemaCXX/type-traits.cpp
@@ -215,6 +215,13 @@ struct HasCopy {
HasCopy(HasCopy& cp);
};
+struct HasTemplateCons {
+ HasVirt Annoying;
+
+ template <typename T>
+ HasTemplateCons(const T&);
+};
+
void has_trivial_default_constructor() {
int t01[T(__has_trivial_constructor(Int))];
int t02[T(__has_trivial_constructor(IntAr))];
@@ -236,6 +243,7 @@ void has_trivial_default_constructor() {
int t18[F(__has_trivial_constructor(VirtAr))];
int t19[F(__has_trivial_constructor(void))];
int t20[F(__has_trivial_constructor(cvoid))];
+ int t21[F(__has_trivial_constructor(HasTemplateCons))];
}
void has_trivial_copy_constructor() {
@@ -259,6 +267,7 @@ void has_trivial_copy_constructor() {
int t18[F(__has_trivial_copy(VirtAr))];
int t19[F(__has_trivial_copy(void))];
int t20[F(__has_trivial_copy(cvoid))];
+ int t21[F(__has_trivial_copy(HasTemplateCons))];
}
void has_trivial_copy_assignment() {
@@ -367,6 +376,7 @@ void has_nothrow_copy() {
int t22[F(__has_nothrow_copy(void))];
int t23[F(__has_nothrow_copy(cvoid))];
int t24[T(__has_nothrow_copy(HasVirtDest))];
+ int t25[T(__has_nothrow_copy(HasTemplateCons))];
}
void has_nothrow_constructor() {
@@ -394,6 +404,7 @@ void has_nothrow_constructor() {
int t21[F(__has_nothrow_constructor(void))];
int t22[F(__has_nothrow_constructor(cvoid))];
int t23[T(__has_nothrow_constructor(HasVirtDest))];
+ int t24[F(__has_nothrow_constructor(HasTemplateCons))];
}
void has_virtual_destructor() {