aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/DeclCXX.h3
-rw-r--r--lib/AST/DeclCXX.cpp22
-rw-r--r--lib/Sema/SemaDeclCXX.cpp30
-rw-r--r--lib/Sema/SemaExprCXX.cpp24
-rw-r--r--test/SemaCXX/type-traits.cpp1
5 files changed, 41 insertions, 39 deletions
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index 3db147c1ab..c4b9292be4 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -859,9 +859,6 @@ public:
/// \brief Set the kind of specialization or template instantiation this is.
void setTemplateSpecializationKind(TemplateSpecializationKind TSK);
-
- /// getDefaultConstructor - Returns the default constructor for this class
- CXXConstructorDecl *getDefaultConstructor();
/// getDestructor - Returns the destructor decl for this class.
CXXDestructorDecl *getDestructor() const;
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index f2f0694826..88301c2d9d 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -577,28 +577,6 @@ CXXRecordDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
assert(false && "Not a class template or member class specialization");
}
-CXXConstructorDecl *
-CXXRecordDecl::getDefaultConstructor() {
- ASTContext &Context = getASTContext();
- QualType ClassType = Context.getTypeDeclType(this);
- DeclarationName ConstructorName
- = Context.DeclarationNames.getCXXConstructorName(
- Context.getCanonicalType(ClassType.getUnqualifiedType()));
-
- DeclContext::lookup_const_iterator Con, ConEnd;
- for (llvm::tie(Con, ConEnd) = lookup(ConstructorName);
- 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())
- return Constructor;
- }
- return 0;
-}
-
CXXDestructorDecl *CXXRecordDecl::getDestructor() const {
ASTContext &Context = getASTContext();
QualType ClassType = Context.getTypeDeclType(this);
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 2d31e8cc9a..d16d9e9763 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -4322,6 +4322,28 @@ namespace {
};
}
+static CXXConstructorDecl *getDefaultConstructorUnsafe(Sema &Self,
+ CXXRecordDecl *D) {
+ ASTContext &Context = Self.Context;
+ QualType ClassType = Context.getTypeDeclType(D);
+ DeclarationName ConstructorName
+ = Context.DeclarationNames.getCXXConstructorName(
+ Context.getCanonicalType(ClassType.getUnqualifiedType()));
+
+ DeclContext::lookup_const_iterator Con, ConEnd;
+ for (llvm::tie(Con, ConEnd) = D->lookup(ConstructorName);
+ 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())
+ return Constructor;
+ }
+ return 0;
+}
+
CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(
CXXRecordDecl *ClassDecl) {
// C++ [class.ctor]p5:
@@ -4349,8 +4371,8 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(
CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
if (!BaseClassDecl->hasDeclaredDefaultConstructor())
ExceptSpec.CalledDecl(DeclareImplicitDefaultConstructor(BaseClassDecl));
- else if (CXXConstructorDecl *Constructor
- = BaseClassDecl->getDefaultConstructor())
+ else if (CXXConstructorDecl *Constructor
+ = getDefaultConstructorUnsafe(*this, BaseClassDecl))
ExceptSpec.CalledDecl(Constructor);
}
}
@@ -4364,7 +4386,7 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(
if (!BaseClassDecl->hasDeclaredDefaultConstructor())
ExceptSpec.CalledDecl(DeclareImplicitDefaultConstructor(BaseClassDecl));
else if (CXXConstructorDecl *Constructor
- = BaseClassDecl->getDefaultConstructor())
+ = getDefaultConstructorUnsafe(*this, BaseClassDecl))
ExceptSpec.CalledDecl(Constructor);
}
}
@@ -4380,7 +4402,7 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(
ExceptSpec.CalledDecl(
DeclareImplicitDefaultConstructor(FieldClassDecl));
else if (CXXConstructorDecl *Constructor
- = FieldClassDecl->getDefaultConstructor())
+ = getDefaultConstructorUnsafe(*this, FieldClassDecl))
ExceptSpec.CalledDecl(Constructor);
}
}
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index d026851f62..b380a4b7a7 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -2145,8 +2145,6 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, QualType T) {
bool FoundConstructor = false;
bool AllNoThrow = true;
unsigned FoundTQs;
- DeclarationName ConstructorName
- = C.DeclarationNames.getCXXConstructorName(C.getCanonicalType(T));
DeclContext::lookup_const_iterator Con, ConEnd;
for (llvm::tie(Con, ConEnd) = Self.LookupConstructors(RD);
Con != ConEnd; ++Con) {
@@ -2155,7 +2153,9 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, QualType T) {
FoundConstructor = true;
const FunctionProtoType *CPT
= Constructor->getType()->getAs<FunctionProtoType>();
- if (!CPT->hasEmptyExceptionSpec()) {
+ // TODO: check whether evaluating default arguments can throw.
+ // For now, we'll be conservative and assume that they can throw.
+ if (!CPT->hasEmptyExceptionSpec() || CPT->getNumArgs() > 1) {
AllNoThrow = false;
break;
}
@@ -2178,13 +2178,17 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, QualType T) {
if (RD->hasTrivialConstructor())
return true;
- if (CXXConstructorDecl *Constructor = RD->getDefaultConstructor()) {
- const FunctionProtoType *CPT
- = Constructor->getType()->getAs<FunctionProtoType>();
- // TODO: check whether evaluating default arguments can throw.
- // For now, we'll be conservative and assume that they can throw.
- if (CPT->hasEmptyExceptionSpec() && CPT->getNumArgs() == 0)
- return true;
+ DeclContext::lookup_const_iterator Con, ConEnd;
+ for (llvm::tie(Con, ConEnd) = Self.LookupConstructors(RD);
+ Con != ConEnd; ++Con) {
+ CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
+ if (Constructor->isDefaultConstructor()) {
+ const FunctionProtoType *CPT
+ = Constructor->getType()->getAs<FunctionProtoType>();
+ // TODO: check whether evaluating default arguments can throw.
+ // For now, we'll be conservative and assume that they can throw.
+ return CPT->hasEmptyExceptionSpec() && CPT->getNumArgs() == 0;
+ }
}
}
return false;
diff --git a/test/SemaCXX/type-traits.cpp b/test/SemaCXX/type-traits.cpp
index 61aba07597..cb88220bb1 100644
--- a/test/SemaCXX/type-traits.cpp
+++ b/test/SemaCXX/type-traits.cpp
@@ -393,6 +393,7 @@ void has_nothrow_constructor() {
int t20[F(__has_nothrow_constructor(HasNoThrowConstructorWithArgs))];
int t21[F(__has_nothrow_constructor(void))];
int t22[F(__has_nothrow_constructor(cvoid))];
+ int t23[T(__has_nothrow_constructor(HasVirtDest))];
}
void has_virtual_destructor() {