diff options
| author | Douglas Gregor <dgregor@apple.com> | 2010-07-03 00:47:00 +0000 |
|---|---|---|
| committer | Douglas Gregor <dgregor@apple.com> | 2010-07-03 00:47:00 +0000 |
| commit | 9672f92f7f2c5a58037ee6ee38004330d80f3372 (patch) | |
| tree | 958a5b6191a0723112eab72105117d24b2975587 /clang/lib/Sema/SemaDeclCXX.cpp | |
| parent | 0664a67fe1cf6bbf93b51153c8cd452409995efb (diff) | |
| download | bcm5719-llvm-9672f92f7f2c5a58037ee6ee38004330d80f3372.tar.gz bcm5719-llvm-9672f92f7f2c5a58037ee6ee38004330d80f3372.zip | |
Lazily declare default constructors. We now delay the construction of
declarations for implicit default constructors, copy constructors,
copy assignment operators, and destructors. On a "simple" translation
unit that includes a bunch of C++ standard library headers, we
generate relatively few of these implicit declarations now:
4/159 implicit default constructors created
18/236 implicit copy constructors created
70/241 implicit copy assignment operators created
0/173 implicit destructors created
And, on this translation unit, this optimization doesn't really
provide any benefit. I'll do some more performance measurements soon,
but this completes the implementation work for <rdar://problem/8151045>.
llvm-svn: 107551
Diffstat (limited to 'clang/lib/Sema/SemaDeclCXX.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 80 |
1 files changed, 66 insertions, 14 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 5c98e2b1db2..4dd5e3f30dd 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -2654,7 +2654,7 @@ namespace { /// definition of the class is complete. void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { if (!ClassDecl->hasUserDeclaredConstructor()) - DeclareImplicitDefaultConstructor(ClassDecl); + ++ASTContext::NumImplicitDefaultConstructors; if (!ClassDecl->hasUserDeclaredCopyConstructor()) ++ASTContext::NumImplicitCopyConstructors; @@ -4156,6 +4156,19 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( // 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. + assert(!ClassDecl->hasUserDeclaredConstructor() && + "Should not build implicit default constructor!"); + + // FIXME: HACK HACK HACK + if (Context.getExternalSource()) { + // This hack ensures that, when using precompiled headers, the lookup + // table in the DeclContext has already loaded the constructor declarations + // so that we can add a new one. The real fix will go into DeclContext, + // when I figure out what that is. + CanQualType T + = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl)); + ClassDecl->lookup(Context.DeclarationNames.getCXXConstructorName(T)); + } // C++ [except.spec]p14: // An implicitly declared special member function (Clause 12) shall have an @@ -4169,20 +4182,28 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( if (B->isVirtual()) // Handled below. continue; - if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) - if (CXXConstructorDecl *Constructor - = cast<CXXRecordDecl>(BaseType->getDecl())->getDefaultConstructor()) + if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) { + CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl()); + if (!BaseClassDecl->hasDeclaredDefaultConstructor()) + ExceptSpec.CalledDecl(DeclareImplicitDefaultConstructor(BaseClassDecl)); + else if (CXXConstructorDecl *Constructor + = BaseClassDecl->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<RecordType>()) - if (CXXConstructorDecl *Constructor - = cast<CXXRecordDecl>(BaseType->getDecl())->getDefaultConstructor()) + if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) { + CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl()); + if (!BaseClassDecl->hasDeclaredDefaultConstructor()) + ExceptSpec.CalledDecl(DeclareImplicitDefaultConstructor(BaseClassDecl)); + else if (CXXConstructorDecl *Constructor + = BaseClassDecl->getDefaultConstructor()) ExceptSpec.CalledDecl(Constructor); + } } // Field destructors. @@ -4190,10 +4211,15 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( FEnd = ClassDecl->field_end(); F != FEnd; ++F) { if (const RecordType *RecordTy - = Context.getBaseElementType(F->getType())->getAs<RecordType>()) - if (CXXConstructorDecl *Constructor - = cast<CXXRecordDecl>(RecordTy->getDecl())->getDefaultConstructor()) + = Context.getBaseElementType(F->getType())->getAs<RecordType>()) { + CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RecordTy->getDecl()); + if (!FieldClassDecl->hasDeclaredDefaultConstructor()) + ExceptSpec.CalledDecl( + DeclareImplicitDefaultConstructor(FieldClassDecl)); + else if (CXXConstructorDecl *Constructor + = FieldClassDecl->getDefaultConstructor()) ExceptSpec.CalledDecl(Constructor); + } } @@ -4219,10 +4245,15 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( DefaultCon->setAccess(AS_public); DefaultCon->setImplicit(); DefaultCon->setTrivial(ClassDecl->hasTrivialConstructor()); + + // Note that we have declared this constructor. + ClassDecl->setDeclaredDefaultConstructor(true); + ++ASTContext::NumImplicitDefaultConstructorsDeclared; + if (Scope *S = getScopeForContext(ClassDecl)) - PushOnScopeChains(DefaultCon, S, true); - else - ClassDecl->addDecl(DefaultCon); + PushOnScopeChains(DefaultCon, S, false); + ClassDecl->addDecl(DefaultCon); + return DefaultCon; } @@ -4612,7 +4643,17 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { // constructor rules. Note that virtual bases are not taken into account // for determining the argument type of the operator. Note also that // operators taking an object instead of a reference are allowed. - // + + + // FIXME: HACK HACK HACK + if (Context.getExternalSource()) { + // This hack ensures that, when using precompiled headers, the lookup + // table in the DeclContext has already loaded the assignment operator + // declarations so that we can add a new one. The real fix will go into + // DeclContext, when I figure out what that is. + ClassDecl->lookup(Context.DeclarationNames.getCXXOperatorName(OO_Equal)); + } + // C++ [class.copy]p10: // If the class definition does not explicitly declare a copy // assignment operator, one is declared implicitly. @@ -5045,6 +5086,17 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( // If the class definition does not explicitly declare a copy // constructor, one is declared implicitly. + // FIXME: HACK HACK HACK + if (Context.getExternalSource()) { + // This hack ensures that, when using precompiled headers, the lookup + // table in the DeclContext has already loaded the constructor declarations + // so that we can add a new one. The real fix will go into DeclContext, + // when I figure out what that is. + CanQualType T + = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl)); + ClassDecl->lookup(Context.DeclarationNames.getCXXConstructorName(T)); + } + // C++ [class.copy]p5: // The implicitly-declared copy constructor for a class X will // have the form |

