From eb8c670d2949eb62005eca36c64c9461f2a2173e Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Thu, 1 Jul 2010 22:31:05 +0000 Subject: [PATCH] Provide exception specifications for implicitly-declared default constructors. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@107437 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/DeclCXX.h | 2 +- lib/AST/DeclCXX.cpp | 3 +- lib/Sema/SemaDeclCXX.cpp | 51 +++++++++++++++++++++++--- test/CXX/except/except.spec/p14-ir.cpp | 26 +++++++++++++ 4 files changed, 75 insertions(+), 7 deletions(-) diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 78f8cb9f0c..a543cf0d5b 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -785,7 +785,7 @@ public: void setTemplateSpecializationKind(TemplateSpecializationKind TSK); /// getDefaultConstructor - Returns the default constructor for this class - CXXConstructorDecl *getDefaultConstructor(ASTContext &Context); + 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 e900165353..9ab44b6385 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -624,7 +624,8 @@ CXXRecordDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) { } CXXConstructorDecl * -CXXRecordDecl::getDefaultConstructor(ASTContext &Context) { +CXXRecordDecl::getDefaultConstructor() { + ASTContext &Context = getASTContext(); QualType ClassType = Context.getTypeDeclType(this); DeclarationName ConstructorName = Context.DeclarationNames.getCXXConstructorName( diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 714814afc1..391541d484 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -2656,9 +2656,6 @@ namespace { /// The scope, if provided, is the class scope. void Sema::AddImplicitlyDeclaredMembersToClass(Scope *S, CXXRecordDecl *ClassDecl) { - // FIXME: Implicit declarations have exception specifications, which are - // the union of the specifications of the implicitly called functions. - if (!ClassDecl->hasUserDeclaredConstructor()) DeclareImplicitDefaultConstructor(S, ClassDecl); @@ -4146,6 +4143,48 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(Scope *S, // user-declared constructor for class X, a default constructor is // implicitly declared. An implicitly-declared default constructor // is an inline public member of its class. + + // C++ [except.spec]p14: + // An implicitly declared special member function (Clause 12) shall have an + // exception-specification. [...] + ImplicitExceptionSpecification ExceptSpec(Context); + + // Direct base-class destructors. + for (CXXRecordDecl::base_class_iterator B = ClassDecl->bases_begin(), + BEnd = ClassDecl->bases_end(); + B != BEnd; ++B) { + if (B->isVirtual()) // Handled below. + continue; + + if (const RecordType *BaseType = B->getType()->getAs()) + if (CXXConstructorDecl *Constructor + = cast(BaseType->getDecl())->getDefaultConstructor()) + ExceptSpec.CalledDecl(Constructor); + } + + // Virtual base-class destructors. + for (CXXRecordDecl::base_class_iterator B = ClassDecl->vbases_begin(), + BEnd = ClassDecl->vbases_end(); + B != BEnd; ++B) { + if (const RecordType *BaseType = B->getType()->getAs()) + if (CXXConstructorDecl *Constructor + = cast(BaseType->getDecl())->getDefaultConstructor()) + ExceptSpec.CalledDecl(Constructor); + } + + // Field destructors. + for (RecordDecl::field_iterator F = ClassDecl->field_begin(), + FEnd = ClassDecl->field_end(); + F != FEnd; ++F) { + if (const RecordType *RecordTy + = Context.getBaseElementType(F->getType())->getAs()) + if (CXXConstructorDecl *Constructor + = cast(RecordTy->getDecl())->getDefaultConstructor()) + ExceptSpec.CalledDecl(Constructor); + } + + + // Create the actual constructor declaration. CanQualType ClassType = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl)); DeclarationName Name @@ -4155,8 +4194,10 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(Scope *S, ClassDecl->getLocation(), Name, Context.getFunctionType(Context.VoidTy, 0, 0, false, 0, - /*FIXME*/false, false, - 0, 0, + ExceptSpec.hasExceptionSpecification(), + ExceptSpec.hasAnyExceptionSpecification(), + ExceptSpec.size(), + ExceptSpec.data(), FunctionType::ExtInfo()), /*TInfo=*/0, /*isExplicit=*/false, diff --git a/test/CXX/except/except.spec/p14-ir.cpp b/test/CXX/except/except.spec/p14-ir.cpp index 646a87e4e4..bc89ce934f 100644 --- a/test/CXX/except/except.spec/p14-ir.cpp +++ b/test/CXX/except/except.spec/p14-ir.cpp @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fexceptions -o - %s | FileCheck %s +// Copy constructor struct X0 { X0(); X0(const X0 &) throw(); @@ -42,3 +43,28 @@ void test(X2 x2, X3 x3, X5 x5) { // CHECK: ret void X5 x5a(x5); } + +// Default constructor +struct X6 { + X6() throw(); +}; + +struct X7 { + X7(); +}; + +struct X8 : X6 { }; +struct X9 : X6, X7 { }; + +void test() { + // CHECK: define linkonce_odr void @_ZN2X8C1Ev + // CHECK-NOT: define + // CHECK: call void @__cxa_call_unexpected + // CHECK-NOT: define + // CHECK: ret void + X8(); + // CHECK: define linkonce_odr void @_ZN2X9C1Ev + // CHECK-NOT: call void @__cxa_call_unexpected + // CHECK: ret void + X9(); +} -- 2.40.0