diff --git a/clang/include/clang/Parse/Action.h b/clang/include/clang/Parse/Action.h index cba3dea5c8ee..b88ea17a675b 100644 --- a/clang/include/clang/Parse/Action.h +++ b/clang/include/clang/Parse/Action.h @@ -1232,6 +1232,8 @@ public: SourceLocation ColonLoc, MemInitTy **MemInits, unsigned NumMemInits){ } + + virtual void ActOnDefaultInitializers(DeclPtrTy ConstructorDecl) {} /// ActOnFinishCXXMemberSpecification - Invoked after all member declarators /// are parsed but *before* parsing of inline method definitions. diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 3ffeb57e5b97..607c4aaa4ed3 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -482,12 +482,81 @@ CXXConstructorDecl::setBaseOrMemberInitializers( ASTContext &C, CXXBaseOrMemberInitializer **Initializers, unsigned NumInitializers) { + // We need to build the initializer AST according to order of construction + // and not what user specified in the Initializers list. + // FIXME. We probably don't need this. But it is cleaner. + CXXRecordDecl *ClassDecl = cast(getDeclContext()); + llvm::SmallVector AllToInit; + // Push virtual bases before others. + for (CXXRecordDecl::base_class_iterator VBase = + ClassDecl->vbases_begin(), + E = ClassDecl->vbases_end(); VBase != E; ++VBase) { + const Type * T = VBase->getType()->getAsRecordType(); + unsigned int i = 0; + for (i = 0; i < NumInitializers; i++) { + CXXBaseOrMemberInitializer *Member = Initializers[i]; + if (Member->isBaseInitializer() && + Member->getBaseClass() == T) { + AllToInit.push_back(Member); + break; + } + } + if (i == NumInitializers) { + CXXBaseOrMemberInitializer *Member = + new CXXBaseOrMemberInitializer(VBase->getType(), 0, 0,SourceLocation()); + AllToInit.push_back(Member); + } + } + for (CXXRecordDecl::base_class_iterator Base = + ClassDecl->bases_begin(), + E = ClassDecl->bases_end(); Base != E; ++Base) { + // Virtuals are in the virtual base list and already constructed. + if (Base->isVirtual()) + continue; + const Type * T = Base->getType()->getAsRecordType(); + unsigned int i = 0; + for (i = 0; i < NumInitializers; i++) { + CXXBaseOrMemberInitializer *Member = Initializers[i]; + if (Member->isBaseInitializer() && Member->getBaseClass() == T) { + AllToInit.push_back(Member); + break; + } + } + if (i == NumInitializers) { + CXXBaseOrMemberInitializer *Member = + new CXXBaseOrMemberInitializer(Base->getType(), 0, 0, SourceLocation()); + AllToInit.push_back(Member); + } + } + // non-static data members. + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + E = ClassDecl->field_end(); Field != E; ++Field) { + unsigned int i = 0; + for (i = 0; i < NumInitializers; i++) { + CXXBaseOrMemberInitializer *Member = Initializers[i]; + if (Member->isMemberInitializer() && Member->getMember() == (*Field)) { + AllToInit.push_back(Member); + break; + } + } + if (i == NumInitializers) { + // FIXME. What do we do with arrays? + QualType FieldType = C.getCanonicalType((*Field)->getType()); + if (FieldType->getAsRecordType()) { + CXXBaseOrMemberInitializer *Member = + new CXXBaseOrMemberInitializer((*Field), 0, 0, SourceLocation()); + AllToInit.push_back(Member); + } + } + } + + NumInitializers = AllToInit.size(); if (NumInitializers > 0) { NumBaseOrMemberInitializers = NumInitializers; BaseOrMemberInitializers = new (C) CXXBaseOrMemberInitializer*[NumInitializers]; for (unsigned Idx = 0; Idx < NumInitializers; ++Idx) - BaseOrMemberInitializers[Idx] = Initializers[Idx]; + BaseOrMemberInitializers[Idx] = AllToInit[Idx]; } } diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp index af6fab7cb188..a2324ab28e3e 100644 --- a/clang/lib/Parse/ParseCXXInlineMethods.cpp +++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp @@ -171,6 +171,10 @@ void Parser::ParseLexedMethodDefs(ParsingClass &Class) { } if (Tok.is(tok::colon)) ParseConstructorInitializer(LM.D); + else { + Actions.ActOnDefaultInitializers(LM.D); + } + // FIXME: What if ParseConstructorInitializer doesn't leave us with a '{'?? ParseFunctionStatementBody(LM.D); } diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 4344fde67652..e01bf23ce6a1 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -1468,6 +1468,7 @@ public: SourceLocation MemberLoc, IdentifierInfo &Member, DeclPtrTy ImplDecl); + virtual void ActOnDefaultInitializers(DeclPtrTy ConstructorDecl); bool ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, FunctionDecl *FDecl, const FunctionProtoType *Proto, diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 17726c64f04c..7d039dc2d675 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -902,6 +902,17 @@ void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl, } } +void Sema::ActOnDefaultInitializers(DeclPtrTy ConstructorDecl) { + if (!ConstructorDecl) + return; + + if (CXXConstructorDecl *Constructor + = dyn_cast(ConstructorDecl.getAs())) + Constructor->setBaseOrMemberInitializers(Context, + (CXXBaseOrMemberInitializer **)0, 0); + +} + namespace { /// PureVirtualMethodCollector - traverses a class and its superclasses /// and determines if it has any pure virtual methods.