diff options
author | dim <dim@FreeBSD.org> | 2013-04-08 18:45:10 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2013-04-08 18:45:10 +0000 |
commit | c72c57c9e9b69944e3e009cd5e209634839581d3 (patch) | |
tree | 4fc2f184c499d106f29a386c452b49e5197bf63d /lib/Sema/SemaDeclCXX.cpp | |
parent | 5b20025c30d23d521e12c1f33ec8fa6b821952cd (diff) | |
download | FreeBSD-src-c72c57c9e9b69944e3e009cd5e209634839581d3.zip FreeBSD-src-c72c57c9e9b69944e3e009cd5e209634839581d3.tar.gz |
Vendor import of clang trunk r178860:
http://llvm.org/svn/llvm-project/cfe/trunk@178860
Diffstat (limited to 'lib/Sema/SemaDeclCXX.cpp')
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 2314 |
1 files changed, 1395 insertions, 919 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 16eddf8..35890e6 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -12,16 +12,11 @@ //===----------------------------------------------------------------------===// #include "clang/Sema/SemaInternal.h" -#include "clang/Sema/CXXFieldCollector.h" -#include "clang/Sema/Scope.h" -#include "clang/Sema/Initialization.h" -#include "clang/Sema/Lookup.h" -#include "clang/Sema/ScopeInfo.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTMutationListener.h" -#include "clang/AST/CharUnits.h" #include "clang/AST/CXXInheritance.h" +#include "clang/AST/CharUnits.h" #include "clang/AST/DeclVisitor.h" #include "clang/AST/EvaluatedExprVisitor.h" #include "clang/AST/ExprCXX.h" @@ -30,12 +25,18 @@ #include "clang/AST/StmtVisitor.h" #include "clang/AST/TypeLoc.h" #include "clang/AST/TypeOrdering.h" -#include "clang/Sema/DeclSpec.h" -#include "clang/Sema/ParsedTemplate.h" #include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/TargetInfo.h" #include "clang/Lex/Preprocessor.h" -#include "llvm/ADT/SmallString.h" +#include "clang/Sema/CXXFieldCollector.h" +#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/Initialization.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/ParsedTemplate.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/ScopeInfo.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallString.h" #include <map> #include <set> @@ -251,7 +252,7 @@ Sema::SetParamDefaultArgument(ParmVarDecl *Param, Expr *Arg, return true; Arg = Result.takeAs<Expr>(); - CheckImplicitConversions(Arg, EqualLoc); + CheckCompletedExpr(Arg, EqualLoc); Arg = MaybeCreateExprWithCleanups(Arg); // Okay: add the default argument to the parameter @@ -351,16 +352,25 @@ void Sema::CheckExtraCXXDefaultArguments(Declarator &D) { // parameter pack. If it is specified in a // parameter-declaration-clause, it shall not occur within a // declarator or abstract-declarator of a parameter-declaration. + bool MightBeFunction = D.isFunctionDeclarationContext(); for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) { DeclaratorChunk &chunk = D.getTypeObject(i); if (chunk.Kind == DeclaratorChunk::Function) { + if (MightBeFunction) { + // This is a function declaration. It can have default arguments, but + // keep looking in case its return type is a function type with default + // arguments. + MightBeFunction = false; + continue; + } for (unsigned argIdx = 0, e = chunk.Fun.NumArgs; argIdx != e; ++argIdx) { ParmVarDecl *Param = cast<ParmVarDecl>(chunk.Fun.ArgInfo[argIdx].Param); if (Param->hasUnparsedDefaultArg()) { CachedTokens *Toks = chunk.Fun.ArgInfo[argIdx].DefaultArgTokens; Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc) - << SourceRange((*Toks)[1].getLocation(), Toks->back().getLocation()); + << SourceRange((*Toks)[1].getLocation(), + Toks->back().getLocation()); delete Toks; chunk.Fun.ArgInfo[argIdx].DefaultArgTokens = 0; } else if (Param->getDefaultArg()) { @@ -369,6 +379,8 @@ void Sema::CheckExtraCXXDefaultArguments(Declarator &D) { Param->setDefaultArg(0); } } + } else if (chunk.Kind != DeclaratorChunk::Paren) { + MightBeFunction = false; } } } @@ -517,19 +529,26 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, diag::err_param_default_argument_member_template_redecl) << WhichKind << NewParam->getDefaultArgRange(); - } else if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(New)) { - CXXSpecialMember NewSM = getSpecialMember(Ctor), - OldSM = getSpecialMember(cast<CXXConstructorDecl>(Old)); - if (NewSM != OldSM) { - Diag(NewParam->getLocation(),diag::warn_default_arg_makes_ctor_special) - << NewParam->getDefaultArgRange() << NewSM; - Diag(Old->getLocation(), diag::note_previous_declaration_special) - << OldSM; - } } } } + // DR1344: If a default argument is added outside a class definition and that + // default argument makes the function a special member function, the program + // is ill-formed. This can only happen for constructors. + if (isa<CXXConstructorDecl>(New) && + New->getMinRequiredArguments() < Old->getMinRequiredArguments()) { + CXXSpecialMember NewSM = getSpecialMember(cast<CXXMethodDecl>(New)), + OldSM = getSpecialMember(cast<CXXMethodDecl>(Old)); + if (NewSM != OldSM) { + ParmVarDecl *NewParam = New->getParamDecl(New->getMinRequiredArguments()); + assert(NewParam->hasDefaultArg()); + Diag(NewParam->getLocation(), diag::err_default_arg_makes_ctor_special) + << NewParam->getDefaultArgRange() << NewSM; + Diag(Old->getLocation(), diag::note_previous_declaration); + } + } + // C++11 [dcl.constexpr]p1: If any declaration of a function or function // template has a constexpr specifier then all its declarations shall // contain the constexpr specifier. @@ -875,7 +894,7 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) { // - its function-body shall be [...] a compound-statement that contains only CompoundStmt *CompBody = cast<CompoundStmt>(Body); - llvm::SmallVector<SourceLocation, 4> ReturnStmts; + SmallVector<SourceLocation, 4> ReturnStmts; for (CompoundStmt::body_iterator BodyIt = CompBody->body_begin(), BodyEnd = CompBody->body_end(); BodyIt != BodyEnd; ++BodyIt) { switch ((*BodyIt)->getStmtClass()) { @@ -985,13 +1004,14 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) { // C++11 [dcl.constexpr]p4: // - every constructor involved in initializing non-static data members and // base class sub-objects shall be a constexpr constructor. - llvm::SmallVector<PartialDiagnosticAt, 8> Diags; + SmallVector<PartialDiagnosticAt, 8> Diags; if (!Expr::isPotentialConstantExpr(Dcl, Diags)) { - Diag(Dcl->getLocation(), diag::err_constexpr_function_never_constant_expr) + Diag(Dcl->getLocation(), diag::ext_constexpr_function_never_constant_expr) << isa<CXXConstructorDecl>(Dcl); for (size_t I = 0, N = Diags.size(); I != N; ++I) Diag(Diags[I].first, Diags[I].second); - return false; + // Don't return false here: we allow this for compatibility in + // system headers. } return true; @@ -1163,6 +1183,7 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, /// 'public bar' and 'virtual private baz' are each base-specifiers. BaseResult Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange, + ParsedAttributes &Attributes, bool Virtual, AccessSpecifier Access, ParsedType basetype, SourceLocation BaseLoc, SourceLocation EllipsisLoc) { @@ -1174,6 +1195,22 @@ Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange, if (!Class) return true; + // We do not support any C++11 attributes on base-specifiers yet. + // Diagnose any attributes we see. + if (!Attributes.empty()) { + for (AttributeList *Attr = Attributes.getList(); Attr; + Attr = Attr->getNext()) { + if (Attr->isInvalid() || + Attr->getKind() == AttributeList::IgnoredAttribute) + continue; + Diag(Attr->getLoc(), + Attr->getKind() == AttributeList::UnknownAttribute + ? diag::warn_unknown_attribute_ignored + : diag::err_base_specifier_attribute) + << Attr->getName(); + } + } + TypeSourceInfo *TInfo = 0; GetTypeFromParser(basetype, &TInfo); @@ -1274,29 +1311,25 @@ void Sema::ActOnBaseSpecifiers(Decl *ClassDecl, CXXBaseSpecifier **Bases, (CXXBaseSpecifier**)(Bases), NumBases); } -static CXXRecordDecl *GetClassForType(QualType T) { - if (const RecordType *RT = T->getAs<RecordType>()) - return cast<CXXRecordDecl>(RT->getDecl()); - else if (const InjectedClassNameType *ICT = T->getAs<InjectedClassNameType>()) - return ICT->getDecl(); - else - return 0; -} - /// \brief Determine whether the type \p Derived is a C++ class that is /// derived from the type \p Base. bool Sema::IsDerivedFrom(QualType Derived, QualType Base) { if (!getLangOpts().CPlusPlus) return false; - CXXRecordDecl *DerivedRD = GetClassForType(Derived); + CXXRecordDecl *DerivedRD = Derived->getAsCXXRecordDecl(); if (!DerivedRD) return false; - CXXRecordDecl *BaseRD = GetClassForType(Base); + CXXRecordDecl *BaseRD = Base->getAsCXXRecordDecl(); if (!BaseRD) return false; - + + // If either the base or the derived type is invalid, don't try to + // check whether one is derived from the other. + if (BaseRD->isInvalidDecl() || DerivedRD->isInvalidDecl()) + return false; + // FIXME: instantiate DerivedRD if necessary. We need a PoI for this. return DerivedRD->hasDefinition() && DerivedRD->isDerivedFrom(BaseRD); } @@ -1307,11 +1340,11 @@ bool Sema::IsDerivedFrom(QualType Derived, QualType Base, CXXBasePaths &Paths) { if (!getLangOpts().CPlusPlus) return false; - CXXRecordDecl *DerivedRD = GetClassForType(Derived); + CXXRecordDecl *DerivedRD = Derived->getAsCXXRecordDecl(); if (!DerivedRD) return false; - CXXRecordDecl *BaseRD = GetClassForType(Base); + CXXRecordDecl *BaseRD = Base->getAsCXXRecordDecl(); if (!BaseRD) return false; @@ -1556,7 +1589,7 @@ static bool InitializationHasSideEffects(const FieldDecl &FD) { /// bitfield width if there is one, 'InitExpr' specifies the initializer if /// one has been parsed, and 'InitStyle' is set if an in-class initializer is /// present (but parsing it has been deferred). -Decl * +NamedDecl * Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, MultiTemplateParamsArg TemplateParameterLists, Expr *BW, const VirtSpecifiers &VS, @@ -1657,7 +1690,36 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, DS.getStorageClassSpec() == DeclSpec::SCS_mutable) && !isFunc); - Decl *Member; + if (DS.isConstexprSpecified() && isInstField) { + SemaDiagnosticBuilder B = + Diag(DS.getConstexprSpecLoc(), diag::err_invalid_constexpr_member); + SourceLocation ConstexprLoc = DS.getConstexprSpecLoc(); + if (InitStyle == ICIS_NoInit) { + B << 0 << 0 << FixItHint::CreateReplacement(ConstexprLoc, "const"); + D.getMutableDeclSpec().ClearConstexprSpec(); + const char *PrevSpec; + unsigned DiagID; + bool Failed = D.getMutableDeclSpec().SetTypeQual(DeclSpec::TQ_const, ConstexprLoc, + PrevSpec, DiagID, getLangOpts()); + (void)Failed; + assert(!Failed && "Making a constexpr member const shouldn't fail"); + } else { + B << 1; + const char *PrevSpec; + unsigned DiagID; + if (D.getMutableDeclSpec().SetStorageClassSpec( + *this, DeclSpec::SCS_static, ConstexprLoc, PrevSpec, DiagID)) { + assert(DS.getStorageClassSpec() == DeclSpec::SCS_mutable && + "This is the only DeclSpec that should fail to be applied"); + B << 1; + } else { + B << 0 << FixItHint::CreateInsertion(ConstexprLoc, "static "); + isInstField = false; + } + } + } + + NamedDecl *Member; if (isInstField) { CXXScopeSpec &SS = D.getCXXScopeSpec(); @@ -1711,7 +1773,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, InitStyle, AS); assert(Member && "HandleField never returns null"); } else { - assert(InitStyle == ICIS_NoInit); + assert(InitStyle == ICIS_NoInit || D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static); Member = HandleDeclarator(S, D, TemplateParameterLists); if (!Member) { @@ -1795,7 +1857,11 @@ namespace { public: typedef EvaluatedExprVisitor<UninitializedFieldVisitor> Inherited; UninitializedFieldVisitor(Sema &S, ValueDecl *VD) : Inherited(S.Context), - S(S), VD(VD) { + S(S) { + if (IndirectFieldDecl *IFD = dyn_cast<IndirectFieldDecl>(VD)) + this->VD = IFD->getAnonField(); + else + this->VD = VD; } void HandleExpr(Expr *E) { @@ -1812,23 +1878,33 @@ namespace { if (MemberExpr *ME = dyn_cast<MemberExpr>(E)) { if (isa<EnumConstantDecl>(ME->getMemberDecl())) - return; + return; + + // FieldME is the inner-most MemberExpr that is not an anonymous struct + // or union. + MemberExpr *FieldME = ME; + Expr *Base = E; while (isa<MemberExpr>(Base)) { - ME = dyn_cast<MemberExpr>(Base); - if (VarDecl *VarD = dyn_cast<VarDecl>(ME->getMemberDecl())) - if (VarD->hasGlobalStorage()) - return; + ME = cast<MemberExpr>(Base); + + if (isa<VarDecl>(ME->getMemberDecl())) + return; + + if (FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl())) + if (!FD->isAnonymousStructOrUnion()) + FieldME = ME; + Base = ME->getBase(); } - if (VD == ME->getMemberDecl() && isa<CXXThisExpr>(Base)) { + if (VD == FieldME->getMemberDecl() && isa<CXXThisExpr>(Base)) { unsigned diag = VD->getType()->isReferenceType() ? diag::warn_reference_field_is_uninit : diag::warn_field_is_uninit; - S.Diag(ME->getExprLoc(), diag) << ME->getMemberNameInfo().getName(); - return; + S.Diag(FieldME->getExprLoc(), diag) << VD; } + return; } if (ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) { @@ -1909,11 +1985,7 @@ Sema::ActOnCXXInClassMemberInitializer(Decl *D, SourceLocation InitLoc, } ExprResult Init = InitExpr; - if (!FD->getType()->isDependentType() && !InitExpr->isTypeDependent() && - !FD->getDeclContext()->isDependentContext()) { - // Note: We don't type-check when we're in a dependent context, because - // the initialization-substitution code does not properly handle direct - // list initialization. We have the same hackaround for ctor-initializers. + if (!FD->getType()->isDependentType() && !InitExpr->isTypeDependent()) { if (isa<InitListExpr>(InitExpr) && isStdInitializerList(FD->getType(), 0)) { Diag(FD->getLocation(), diag::warn_dangling_std_initializer_list) << /*at end of ctor*/1 << InitExpr->getSourceRange(); @@ -1930,14 +2002,12 @@ Sema::ActOnCXXInClassMemberInitializer(Decl *D, SourceLocation InitLoc, FD->setInvalidDecl(); return; } - - CheckImplicitConversions(Init.get(), InitLoc); } - // C++0x [class.base.init]p7: + // C++11 [class.base.init]p7: // The initialization of each base and member constitutes a // full-expression. - Init = MaybeCreateExprWithCleanups(Init); + Init = ActOnFinishFullExpr(Init.take(), InitLoc); if (Init.isInvalid()) { FD->setInvalidDecl(); return; @@ -2096,10 +2166,10 @@ Sema::BuildMemInitializer(Decl *ConstructorD, // Look for a member, first. DeclContext::lookup_result Result = ClassDecl->lookup(MemberOrBase); - if (Result.first != Result.second) { + if (!Result.empty()) { ValueDecl *Member; - if ((Member = dyn_cast<FieldDecl>(*Result.first)) || - (Member = dyn_cast<IndirectFieldDecl>(*Result.first))) { + if ((Member = dyn_cast<FieldDecl>(Result.front())) || + (Member = dyn_cast<IndirectFieldDecl>(Result.front()))) { if (EllipsisLoc.isValid()) Diag(EllipsisLoc, diag::err_pack_expansion_member_init) << MemberOrBase @@ -2295,10 +2365,13 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init, if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) { Args = ParenList->getExprs(); NumArgs = ParenList->getNumExprs(); - } else { - InitListExpr *InitList = cast<InitListExpr>(Init); + } else if (InitListExpr *InitList = dyn_cast<InitListExpr>(Init)) { Args = InitList->getInits(); NumArgs = InitList->getNumInits(); + } else { + // Template instantiation doesn't reconstruct ParenListExprs for us. + Args = &Init; + NumArgs = 1; } if (getDiagnostics().getDiagnosticLevel(diag::warn_field_is_uninit, IdLoc) @@ -2349,29 +2422,15 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init, if (MemberInit.isInvalid()) return true; - CheckImplicitConversions(MemberInit.get(), - InitRange.getBegin()); - - // C++0x [class.base.init]p7: + // C++11 [class.base.init]p7: // The initialization of each base and member constitutes a // full-expression. - MemberInit = MaybeCreateExprWithCleanups(MemberInit); + MemberInit = ActOnFinishFullExpr(MemberInit.get(), InitRange.getBegin()); if (MemberInit.isInvalid()) return true; - // If we are in a dependent context, template instantiation will - // perform this type-checking again. Just save the arguments that we - // received. - // FIXME: This isn't quite ideal, since our ASTs don't capture all - // of the information that we have about the member - // initializer. However, deconstructing the ASTs is a dicey process, - // and this approach is far more likely to get the corner cases right. - if (CurContext->isDependentContext()) { - // The existing Init will do fine. - } else { - Init = MemberInit.get(); - CheckForDanglingReferenceOrPointer(*this, Member, Init, IdLoc); - } + Init = MemberInit.get(); + CheckForDanglingReferenceOrPointer(*this, Member, Init, IdLoc); } if (DirectMember) { @@ -2389,7 +2448,7 @@ MemInitResult Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init, CXXRecordDecl *ClassDecl) { SourceLocation NameLoc = TInfo->getTypeLoc().getLocalSourceRange().getBegin(); - if (!LangOpts.CPlusPlus0x) + if (!LangOpts.CPlusPlus11) return Diag(NameLoc, diag::err_delegating_ctor) << TInfo->getTypeLoc().getLocalSourceRange(); Diag(NameLoc, diag::warn_cxx98_compat_delegating_ctor); @@ -2421,12 +2480,11 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init, assert(cast<CXXConstructExpr>(DelegationInit.get())->getConstructor() && "Delegating constructor with no target?"); - CheckImplicitConversions(DelegationInit.get(), InitRange.getBegin()); - - // C++0x [class.base.init]p7: + // C++11 [class.base.init]p7: // The initialization of each base and member constitutes a // full-expression. - DelegationInit = MaybeCreateExprWithCleanups(DelegationInit); + DelegationInit = ActOnFinishFullExpr(DelegationInit.get(), + InitRange.getBegin()); if (DelegationInit.isInvalid()) return true; @@ -2555,12 +2613,10 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, if (BaseInit.isInvalid()) return true; - CheckImplicitConversions(BaseInit.get(), InitRange.getBegin()); - - // C++0x [class.base.init]p7: - // The initialization of each base and member constitutes a + // C++11 [class.base.init]p7: + // The initialization of each base and member constitutes a // full-expression. - BaseInit = MaybeCreateExprWithCleanups(BaseInit); + BaseInit = ActOnFinishFullExpr(BaseInit.get(), InitRange.getBegin()); if (BaseInit.isInvalid()) return true; @@ -2582,9 +2638,10 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, } // Create a static_cast\<T&&>(expr). -static Expr *CastForMoving(Sema &SemaRef, Expr *E) { - QualType ExprType = E->getType(); - QualType TargetType = SemaRef.Context.getRValueReferenceType(ExprType); +static Expr *CastForMoving(Sema &SemaRef, Expr *E, QualType T = QualType()) { + if (T.isNull()) T = E->getType(); + QualType TargetType = SemaRef.BuildReferenceType( + T, /*SpelledAsLValue*/false, SourceLocation(), DeclarationName()); SourceLocation ExprLoc = E->getLocStart(); TypeSourceInfo *TargetLoc = SemaRef.Context.getTrivialTypeSourceInfo( TargetType, ExprLoc); @@ -2599,7 +2656,8 @@ static Expr *CastForMoving(Sema &SemaRef, Expr *E) { enum ImplicitInitializerKind { IIK_Default, IIK_Copy, - IIK_Move + IIK_Move, + IIK_Inherit }; static bool @@ -2615,6 +2673,35 @@ BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, ExprResult BaseInit; switch (ImplicitInitKind) { + case IIK_Inherit: { + const CXXRecordDecl *Inherited = + Constructor->getInheritedConstructor()->getParent(); + const CXXRecordDecl *Base = BaseSpec->getType()->getAsCXXRecordDecl(); + if (Base && Inherited->getCanonicalDecl() == Base->getCanonicalDecl()) { + // C++11 [class.inhctor]p8: + // Each expression in the expression-list is of the form + // static_cast<T&&>(p), where p is the name of the corresponding + // constructor parameter and T is the declared type of p. + SmallVector<Expr*, 16> Args; + for (unsigned I = 0, E = Constructor->getNumParams(); I != E; ++I) { + ParmVarDecl *PD = Constructor->getParamDecl(I); + ExprResult ArgExpr = + SemaRef.BuildDeclRefExpr(PD, PD->getType().getNonReferenceType(), + VK_LValue, SourceLocation()); + if (ArgExpr.isInvalid()) + return true; + Args.push_back(CastForMoving(SemaRef, ArgExpr.take(), PD->getType())); + } + + InitializationKind InitKind = InitializationKind::CreateDirect( + Constructor->getLocation(), SourceLocation(), SourceLocation()); + InitializationSequence InitSeq(SemaRef, InitEntity, InitKind, + Args.data(), Args.size()); + BaseInit = InitSeq.Perform(SemaRef, InitEntity, InitKind, Args); + break; + } + } + // Fall through. case IIK_Default: { InitializationKind InitKind = InitializationKind::CreateDefault(Constructor->getLocation()); @@ -2765,7 +2852,7 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, = VarDecl::Create(SemaRef.Context, SemaRef.CurContext, Loc, Loc, IterationVarName, SizeType, SemaRef.Context.getTrivialTypeSourceInfo(SizeType, Loc), - SC_None, SC_None); + SC_None); IndexVariables.push_back(IterationVar); // Create a reference to the iteration variable. @@ -2837,7 +2924,8 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, return false; } - assert(ImplicitInitKind == IIK_Default && "Unhandled implicit init kind!"); + assert((ImplicitInitKind == IIK_Default || ImplicitInitKind == IIK_Inherit) && + "Unhandled implicit init kind!"); QualType FieldBaseElementType = SemaRef.Context.getBaseElementType(Field->getType()); @@ -2928,6 +3016,8 @@ struct BaseAndFieldInfo { IIK = IIK_Copy; else if (Generated && Ctor->isMoveConstructor()) IIK = IIK_Move; + else if (Ctor->getInheritedConstructor()) + IIK = IIK_Inherit; else IIK = IIK_Default; } @@ -2939,6 +3029,7 @@ struct BaseAndFieldInfo { return true; case IIK_Default: + case IIK_Inherit: return false; } @@ -3059,19 +3150,17 @@ Sema::SetDelegatingInitializer(CXXConstructorDecl *Constructor, return false; } -bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, - CXXCtorInitializer **Initializers, - unsigned NumInitializers, - bool AnyErrors) { +bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, bool AnyErrors, + ArrayRef<CXXCtorInitializer *> Initializers) { if (Constructor->isDependentContext()) { // Just store the initializers as written, they will be checked during // instantiation. - if (NumInitializers > 0) { - Constructor->setNumCtorInitializers(NumInitializers); + if (!Initializers.empty()) { + Constructor->setNumCtorInitializers(Initializers.size()); CXXCtorInitializer **baseOrMemberInitializers = - new (Context) CXXCtorInitializer*[NumInitializers]; - memcpy(baseOrMemberInitializers, Initializers, - NumInitializers * sizeof(CXXCtorInitializer*)); + new (Context) CXXCtorInitializer*[Initializers.size()]; + memcpy(baseOrMemberInitializers, Initializers.data(), + Initializers.size() * sizeof(CXXCtorInitializer*)); Constructor->setCtorInitializers(baseOrMemberInitializers); } @@ -3092,7 +3181,7 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, bool HadError = false; - for (unsigned i = 0; i < NumInitializers; i++) { + for (unsigned i = 0; i < Initializers.size(); i++) { CXXCtorInitializer *Member = Initializers[i]; if (Member->isBaseInitializer()) @@ -3168,7 +3257,7 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, // If we're not generating the implicit copy/move constructor, then we'll // handle anonymous struct/union fields based on their individual // indirect fields. - if (F->isAnonymousStructOrUnion() && Info.IIK == IIK_Default) + if (F->isAnonymousStructOrUnion() && !Info.isImplicitCopyOrMove()) continue; if (CollectFieldInitializer(*this, Info, F)) @@ -3177,7 +3266,7 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, } // Beyond this point, we only consider default initialization. - if (Info.IIK != IIK_Default) + if (Info.isImplicitCopyOrMove()) continue; if (IndirectFieldDecl *F = dyn_cast<IndirectFieldDecl>(*Mem)) { @@ -3195,7 +3284,7 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, } } - NumInitializers = Info.AllToInit.size(); + unsigned NumInitializers = Info.AllToInit.size(); if (NumInitializers > 0) { Constructor->setNumCtorInitializers(NumInitializers); CXXCtorInitializer **baseOrMemberInitializers = @@ -3213,13 +3302,17 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, return HadError; } -static void *GetKeyForTopLevelField(FieldDecl *Field) { - // For anonymous unions, use the class declaration as the key. +static void PopulateKeysForFields(FieldDecl *Field, SmallVectorImpl<const void*> &IdealInits) { if (const RecordType *RT = Field->getType()->getAs<RecordType>()) { - if (RT->getDecl()->isAnonymousStructOrUnion()) - return static_cast<void *>(RT->getDecl()); + const RecordDecl *RD = RT->getDecl(); + if (RD->isAnonymousStructOrUnion()) { + for (RecordDecl::field_iterator Field = RD->field_begin(), + E = RD->field_end(); Field != E; ++Field) + PopulateKeysForFields(*Field, IdealInits); + return; + } } - return static_cast<void *>(Field); + IdealInits.push_back(Field); } static void *GetKeyForBase(ASTContext &Context, QualType BaseType) { @@ -3231,40 +3324,19 @@ static void *GetKeyForMember(ASTContext &Context, if (!Member->isAnyMemberInitializer()) return GetKeyForBase(Context, QualType(Member->getBaseClass(), 0)); - // For fields injected into the class via declaration of an anonymous union, - // use its anonymous union class declaration as the unique key. - FieldDecl *Field = Member->getAnyMember(); - - // If the field is a member of an anonymous struct or union, our key - // is the anonymous record decl that's a direct child of the class. - RecordDecl *RD = Field->getParent(); - if (RD->isAnonymousStructOrUnion()) { - while (true) { - RecordDecl *Parent = cast<RecordDecl>(RD->getDeclContext()); - if (Parent->isAnonymousStructOrUnion()) - RD = Parent; - else - break; - } - - return static_cast<void *>(RD); - } - - return static_cast<void *>(Field); + return Member->getAnyMember(); } -static void -DiagnoseBaseOrMemInitializerOrder(Sema &SemaRef, - const CXXConstructorDecl *Constructor, - CXXCtorInitializer **Inits, - unsigned NumInits) { +static void DiagnoseBaseOrMemInitializerOrder( + Sema &SemaRef, const CXXConstructorDecl *Constructor, + ArrayRef<CXXCtorInitializer *> Inits) { if (Constructor->getDeclContext()->isDependentContext()) return; // Don't check initializers order unless the warning is enabled at the // location of at least one initializer. bool ShouldCheckOrder = false; - for (unsigned InitIndex = 0; InitIndex != NumInits; ++InitIndex) { + for (unsigned InitIndex = 0; InitIndex != Inits.size(); ++InitIndex) { CXXCtorInitializer *Init = Inits[InitIndex]; if (SemaRef.Diags.getDiagnosticLevel(diag::warn_initializer_out_of_order, Init->getSourceLocation()) @@ -3303,14 +3375,14 @@ DiagnoseBaseOrMemInitializerOrder(Sema &SemaRef, if (Field->isUnnamedBitfield()) continue; - IdealInitKeys.push_back(GetKeyForTopLevelField(*Field)); + PopulateKeysForFields(*Field, IdealInitKeys); } unsigned NumIdealInits = IdealInitKeys.size(); unsigned IdealIndex = 0; CXXCtorInitializer *PrevInit = 0; - for (unsigned InitIndex = 0; InitIndex != NumInits; ++InitIndex) { + for (unsigned InitIndex = 0; InitIndex != Inits.size(); ++InitIndex) { CXXCtorInitializer *Init = Inits[InitIndex]; void *InitKey = GetKeyForMember(SemaRef.Context, Init); @@ -3360,7 +3432,7 @@ bool CheckRedundantInit(Sema &S, return false; } - if (FieldDecl *Field = Init->getMember()) + if (FieldDecl *Field = Init->getAnyMember()) S.Diag(Init->getSourceLocation(), diag::err_multiple_mem_initialization) << Field->getDeclName() @@ -3420,8 +3492,7 @@ bool CheckRedundantUnionInit(Sema &S, /// ActOnMemInitializers - Handle the member initializers for a constructor. void Sema::ActOnMemInitializers(Decl *ConstructorDecl, SourceLocation ColonLoc, - CXXCtorInitializer **meminits, - unsigned NumMemInits, + ArrayRef<CXXCtorInitializer*> MemInits, bool AnyErrors) { if (!ConstructorDecl) return; @@ -3436,9 +3507,6 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl, return; } - CXXCtorInitializer **MemInits = - reinterpret_cast<CXXCtorInitializer **>(meminits); - // Mapping for the duplicate initializers check. // For member initializers, this is keyed with a FieldDecl*. // For base initializers, this is keyed with a Type*. @@ -3448,7 +3516,7 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl, RedundantUnionMap MemberUnions; bool HadError = false; - for (unsigned i = 0; i < NumMemInits; i++) { + for (unsigned i = 0; i < MemInits.size(); i++) { CXXCtorInitializer *Init = MemInits[i]; // Set the source order index. @@ -3466,7 +3534,7 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl, } else { assert(Init->isDelegatingInitializer()); // This must be the only initializer - if (NumMemInits != 1) { + if (MemInits.size() != 1) { Diag(Init->getSourceLocation(), diag::err_delegating_initializer_alone) << Init->getSourceRange() << MemInits[i ? 0 : 1]->getSourceRange(); @@ -3481,9 +3549,9 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl, if (HadError) return; - DiagnoseBaseOrMemInitializerOrder(*this, Constructor, MemInits, NumMemInits); + DiagnoseBaseOrMemInitializerOrder(*this, Constructor, MemInits); - SetCtorInitializers(Constructor, MemInits, NumMemInits, AnyErrors); + SetCtorInitializers(Constructor, AnyErrors, MemInits); } void @@ -3605,7 +3673,7 @@ void Sema::ActOnDefaultCtorInitializers(Decl *CDtorDecl) { if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(CDtorDecl)) - SetCtorInitializers(Constructor, 0, 0, /*AnyErrors=*/false); + SetCtorInitializers(Constructor, /*AnyErrors=*/false); } bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, @@ -3748,7 +3816,7 @@ struct CheckAbstractUsage { switch (TL.getTypeLocClass()) { #define ABSTRACT_TYPELOC(CLASS, PARENT) #define TYPELOC(CLASS, PARENT) \ - case TypeLoc::CLASS: Check(cast<CLASS##TypeLoc>(TL), Sel); break; + case TypeLoc::CLASS: Check(TL.castAs<CLASS##TypeLoc>(), Sel); break; #include "clang/AST/TypeLocNodes.def" } } @@ -3933,9 +4001,10 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { // C++ [class.mem]p14: // In addition, if class T has a user-declared constructor (12.1), every // non-static data member of class T shall have a name different from T. - for (DeclContext::lookup_result R = Record->lookup(Record->getDeclName()); - R.first != R.second; ++R.first) { - NamedDecl *D = *R.first; + DeclContext::lookup_result R = Record->lookup(Record->getDeclName()); + for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; + ++I) { + NamedDecl *D = *I; if ((isa<FieldDecl>(D) && Record->hasUserDeclaredConstructor()) || isa<IndirectFieldDecl>(D)) { Diag(D->getLocation(), diag::err_member_name_of_class) @@ -3958,18 +4027,34 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { DiagnoseAbstractType(Record); } - // See if a method overloads virtual methods in a base - /// class without overriding any. if (!Record->isDependentType()) { for (CXXRecordDecl::method_iterator M = Record->method_begin(), MEnd = Record->method_end(); M != MEnd; ++M) { + // See if a method overloads virtual methods in a base + // class without overriding any. if (!M->isStatic()) DiagnoseHiddenVirtualMethods(Record, *M); + + // Check whether the explicitly-defaulted special members are valid. + if (!M->isInvalidDecl() && M->isExplicitlyDefaulted()) + CheckExplicitlyDefaultedSpecialMember(*M); + + // For an explicitly defaulted or deleted special member, we defer + // determining triviality until the class is complete. That time is now! + if (!M->isImplicit() && !M->isUserProvided()) { + CXXSpecialMember CSM = getSpecialMember(*M); + if (CSM != CXXInvalid) { + M->setTrivial(SpecialMemberIsTrivial(*M, CSM)); + + // Inform the class that we've finished declaring this member. + Record->finishedDefaultedOrDeletedMember(*M); + } + } } } - // C++0x [dcl.constexpr]p8: A constexpr specifier for a non-static member + // C++11 [dcl.constexpr]p8: A constexpr specifier for a non-static member // function that is not a constructor declares that member function to be // const. [...] The class of which that function is a member shall be // a literal type. @@ -3977,7 +4062,10 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { // If the class has virtual bases, any constexpr members will already have // been diagnosed by the checks performed on the member declaration, so // suppress this (less useful) diagnostic. - if (LangOpts.CPlusPlus0x && !Record->isDependentType() && + // + // We delay this until we know whether an explicitly-defaulted (or deleted) + // destructor for the class is trivial. + if (LangOpts.CPlusPlus11 && !Record->isDependentType() && !Record->isLiteral() && !Record->getNumVBases()) { for (CXXRecordDecl::method_iterator M = Record->method_begin(), MEnd = Record->method_end(); @@ -4005,22 +4093,14 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { } } - // Declare inherited constructors. We do this eagerly here because: - // - The standard requires an eager diagnostic for conflicting inherited + // Declare inheriting constructors. We do this eagerly here because: + // - The standard requires an eager diagnostic for conflicting inheriting // constructors from different classes. // - The lazy declaration of the other implicit constructors is so as to not // waste space and performance on classes that are not meant to be // instantiated (e.g. meta-functions). This doesn't apply to classes that - // have inherited constructors. - DeclareInheritedConstructors(Record); -} - -void Sema::CheckExplicitlyDefaultedMethods(CXXRecordDecl *Record) { - for (CXXRecordDecl::method_iterator MI = Record->method_begin(), - ME = Record->method_end(); - MI != ME; ++MI) - if (!MI->isInvalidDecl() && MI->isExplicitlyDefaulted()) - CheckExplicitlyDefaultedSpecialMember(*MI); + // have inheriting constructors. + DeclareInheritingConstructors(Record); } /// Is the special member function which would be selected to perform the @@ -4043,7 +4123,7 @@ static bool specialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl, static bool defaultedSpecialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl, Sema::CXXSpecialMember CSM, bool ConstArg) { - if (!S.getLangOpts().CPlusPlus0x) + if (!S.getLangOpts().CPlusPlus11) return false; // C++11 [dcl.constexpr]p4: @@ -4136,7 +4216,9 @@ computeImplicitExceptionSpec(Sema &S, SourceLocation Loc, CXXMethodDecl *MD) { case Sema::CXXInvalid: break; } - llvm_unreachable("only special members have implicit exception specs"); + assert(cast<CXXConstructorDecl>(MD)->getInheritedConstructor() && + "only special members have implicit exception specs"); + return S.ComputeInheritingCtorExceptionSpec(cast<CXXConstructorDecl>(MD)); } static void @@ -4145,8 +4227,7 @@ updateExceptionSpec(Sema &S, FunctionDecl *FD, const FunctionProtoType *FPT, FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); ExceptSpec.getEPI(EPI); const FunctionProtoType *NewFPT = cast<FunctionProtoType>( - S.Context.getFunctionType(FPT->getResultType(), FPT->arg_type_begin(), - FPT->getNumArgs(), EPI)); + S.Context.getFunctionType(FPT->getResultType(), FPT->getArgTypes(), EPI)); FD->setType(QualType(NewFPT, 0)); } @@ -4172,9 +4253,6 @@ void Sema::EvaluateImplicitExceptionSpec(SourceLocation Loc, CXXMethodDecl *MD) CanonicalFPT, ExceptSpec); } -static bool isImplicitCopyCtorArgConst(Sema &S, CXXRecordDecl *ClassDecl); -static bool isImplicitCopyAssignmentArgConst(Sema &S, CXXRecordDecl *ClassDecl); - void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { CXXRecordDecl *RD = MD->getParent(); CXXSpecialMember CSM = getSpecialMember(MD); @@ -4205,37 +4283,19 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { Diag(MD->getLocation(), diag::err_defaulted_special_member_params) << CSM << MD->getSourceRange(); HadError = true; + } else if (MD->isVariadic()) { + Diag(MD->getLocation(), diag::err_defaulted_special_member_variadic) + << CSM << MD->getSourceRange(); + HadError = true; } const FunctionProtoType *Type = MD->getType()->getAs<FunctionProtoType>(); - // Compute argument constness, constexpr, and triviality. bool CanHaveConstParam = false; - bool Trivial = false; - switch (CSM) { - case CXXDefaultConstructor: - Trivial = RD->hasTrivialDefaultConstructor(); - break; - case CXXCopyConstructor: - CanHaveConstParam = isImplicitCopyCtorArgConst(*this, RD); - Trivial = RD->hasTrivialCopyConstructor(); - break; - case CXXCopyAssignment: - CanHaveConstParam = isImplicitCopyAssignmentArgConst(*this, RD); - Trivial = RD->hasTrivialCopyAssignment(); - break; - case CXXMoveConstructor: - Trivial = RD->hasTrivialMoveConstructor(); - break; - case CXXMoveAssignment: - Trivial = RD->hasTrivialMoveAssignment(); - break; - case CXXDestructor: - Trivial = RD->hasTrivialDestructor(); - break; - case CXXInvalid: - llvm_unreachable("non-special member explicitly defaulted!"); - } + if (CSM == CXXCopyConstructor) + CanHaveConstParam = RD->implicitCopyConstructorHasConstParam(); + else if (CSM == CXXCopyAssignment) + CanHaveConstParam = RD->implicitCopyAssignmentHasConstParam(); QualType ReturnType = Context.VoidTy; if (CSM == CXXCopyAssignment || CSM == CXXMoveAssignment) { @@ -4284,14 +4344,6 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { } HadError = true; } - - // If a function is explicitly defaulted on its first declaration, it shall - // have the same parameter type as if it had been implicitly declared. - // (Presumably this is to prevent it from being trivial?) - if (!HasConstParam && CanHaveConstParam && First) - Diag(MD->getLocation(), - diag::err_defaulted_special_member_copy_non_const_param) - << (CSM == CXXCopyAssignment); } else if (ExpectedParams) { // A copy assignment operator can take its argument by value, but a // defaulted one cannot. @@ -4300,16 +4352,6 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { HadError = true; } - // Rebuild the type with the implicit exception specification added, if we - // are going to need it. - const FunctionProtoType *ImplicitType = 0; - if (First || Type->hasExceptionSpec()) { - FunctionProtoType::ExtProtoInfo EPI = Type->getExtProtoInfo(); - computeImplicitExceptionSpec(*this, MD->getLocation(), MD).getEPI(EPI); - ImplicitType = cast<FunctionProtoType>( - Context.getFunctionType(ReturnType, &ArgType, ExpectedParams, EPI)); - } - // C++11 [dcl.fct.def.default]p2: // An explicitly-defaulted function may be declared constexpr only if it // would have been implicitly declared as constexpr, @@ -4324,13 +4366,23 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { // FIXME: Explain why the constructor can't be constexpr. HadError = true; } + // and may have an explicit exception-specification only if it is compatible // with the exception-specification on the implicit declaration. - if (Type->hasExceptionSpec() && - CheckEquivalentExceptionSpec( - PDiag(diag::err_incorrect_defaulted_exception_spec) << CSM, - PDiag(), ImplicitType, SourceLocation(), Type, MD->getLocation())) - HadError = true; + if (Type->hasExceptionSpec()) { + // Delay the check if this is the first declaration of the special member, + // since we may not have parsed some necessary in-class initializers yet. + if (First) { + // If the exception specification needs to be instantiated, do so now, + // before we clobber it with an EST_Unevaluated specification below. + if (Type->getExceptionSpecType() == EST_Uninstantiated) { + InstantiateExceptionSpec(MD->getLocStart(), MD); + Type = MD->getType()->getAs<FunctionProtoType>(); + } + DelayedDefaultedMemberExceptionSpecs.push_back(std::make_pair(MD, Type)); + } else + CheckExplicitlyDefaultedMemberExceptionSpec(MD, Type); + } // If a function is explicitly defaulted on its first declaration, if (First) { @@ -4340,16 +4392,18 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { // -- it is implicitly considered to have the same exception-specification // as if it had been implicitly declared, - MD->setType(QualType(ImplicitType, 0)); - - // Such a function is also trivial if the implicitly-declared function - // would have been. - MD->setTrivial(Trivial); + FunctionProtoType::ExtProtoInfo EPI = Type->getExtProtoInfo(); + EPI.ExceptionSpecType = EST_Unevaluated; + EPI.ExceptionSpecDecl = MD; + MD->setType(Context.getFunctionType(ReturnType, + ArrayRef<QualType>(&ArgType, + ExpectedParams), + EPI)); } if (ShouldDeleteSpecialMember(MD, CSM)) { if (First) { - MD->setDeletedAsWritten(); + SetDeclDeleted(MD, MD->getLocation()); } else { // C++11 [dcl.fct.def.default]p4: // [For a] user-provided explicitly-defaulted function [...] if such a @@ -4363,6 +4417,36 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { MD->setInvalidDecl(); } +/// Check whether the exception specification provided for an +/// explicitly-defaulted special member matches the exception specification +/// that would have been generated for an implicit special member, per +/// C++11 [dcl.fct.def.default]p2. +void Sema::CheckExplicitlyDefaultedMemberExceptionSpec( + CXXMethodDecl *MD, const FunctionProtoType *SpecifiedType) { + // Compute the implicit exception specification. + FunctionProtoType::ExtProtoInfo EPI; + computeImplicitExceptionSpec(*this, MD->getLocation(), MD).getEPI(EPI); + const FunctionProtoType *ImplicitType = cast<FunctionProtoType>( + Context.getFunctionType(Context.VoidTy, ArrayRef<QualType>(), EPI)); + + // Ensure that it matches. + CheckEquivalentExceptionSpec( + PDiag(diag::err_incorrect_defaulted_exception_spec) + << getSpecialMember(MD), PDiag(), + ImplicitType, SourceLocation(), + SpecifiedType, MD->getLocation()); +} + +void Sema::CheckDelayedExplicitlyDefaultedMemberExceptionSpecs() { + for (unsigned I = 0, N = DelayedDefaultedMemberExceptionSpecs.size(); + I != N; ++I) + CheckExplicitlyDefaultedMemberExceptionSpec( + DelayedDefaultedMemberExceptionSpecs[I].first, + DelayedDefaultedMemberExceptionSpecs[I].second); + + DelayedDefaultedMemberExceptionSpecs.clear(); +} + namespace { struct SpecialMemberDeletionInfo { Sema &S; @@ -4688,7 +4772,7 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, return false; CXXRecordDecl *RD = MD->getParent(); assert(!RD->isDependentType() && "do deletion after instantiation"); - if (!LangOpts.CPlusPlus0x || RD->isInvalidDecl()) + if (!LangOpts.CPlusPlus11 || RD->isInvalidDecl()) return false; // C++11 [expr.lambda.prim]p19: @@ -4722,12 +4806,28 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, if (RD->hasUserDeclaredMoveConstructor() && (!getLangOpts().MicrosoftMode || CSM == CXXCopyConstructor)) { if (!Diagnose) return true; - UserDeclaredMove = RD->getMoveConstructor(); + + // Find any user-declared move constructor. + for (CXXRecordDecl::ctor_iterator I = RD->ctor_begin(), + E = RD->ctor_end(); I != E; ++I) { + if (I->isMoveConstructor()) { + UserDeclaredMove = *I; + break; + } + } assert(UserDeclaredMove); } else if (RD->hasUserDeclaredMoveAssignment() && (!getLangOpts().MicrosoftMode || CSM == CXXCopyAssignment)) { if (!Diagnose) return true; - UserDeclaredMove = RD->getMoveAssignmentOperator(); + + // Find any user-declared move assignment operator. + for (CXXRecordDecl::method_iterator I = RD->method_begin(), + E = RD->method_end(); I != E; ++I) { + if (I->isMoveAssignmentOperator()) { + UserDeclaredMove = *I; + break; + } + } assert(UserDeclaredMove); } @@ -4783,6 +4883,422 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, return false; } +/// Perform lookup for a special member of the specified kind, and determine +/// whether it is trivial. If the triviality can be determined without the +/// lookup, skip it. This is intended for use when determining whether a +/// special member of a containing object is trivial, and thus does not ever +/// perform overload resolution for default constructors. +/// +/// If \p Selected is not \c NULL, \c *Selected will be filled in with the +/// member that was most likely to be intended to be trivial, if any. +static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD, + Sema::CXXSpecialMember CSM, unsigned Quals, + CXXMethodDecl **Selected) { + if (Selected) + *Selected = 0; + + switch (CSM) { + case Sema::CXXInvalid: + llvm_unreachable("not a special member"); + + case Sema::CXXDefaultConstructor: + // C++11 [class.ctor]p5: + // A default constructor is trivial if: + // - all the [direct subobjects] have trivial default constructors + // + // Note, no overload resolution is performed in this case. + if (RD->hasTrivialDefaultConstructor()) + return true; + + if (Selected) { + // If there's a default constructor which could have been trivial, dig it + // out. Otherwise, if there's any user-provided default constructor, point + // to that as an example of why there's not a trivial one. + CXXConstructorDecl *DefCtor = 0; + if (RD->needsImplicitDefaultConstructor()) + S.DeclareImplicitDefaultConstructor(RD); + for (CXXRecordDecl::ctor_iterator CI = RD->ctor_begin(), + CE = RD->ctor_end(); CI != CE; ++CI) { + if (!CI->isDefaultConstructor()) + continue; + DefCtor = *CI; + if (!DefCtor->isUserProvided()) + break; + } + + *Selected = DefCtor; + } + + return false; + + case Sema::CXXDestructor: + // C++11 [class.dtor]p5: + // A destructor is trivial if: + // - all the direct [subobjects] have trivial destructors + if (RD->hasTrivialDestructor()) + return true; + + if (Selected) { + if (RD->needsImplicitDestructor()) + S.DeclareImplicitDestructor(RD); + *Selected = RD->getDestructor(); + } + + return false; + + case Sema::CXXCopyConstructor: + // C++11 [class.copy]p12: + // A copy constructor is trivial if: + // - the constructor selected to copy each direct [subobject] is trivial + if (RD->hasTrivialCopyConstructor()) { + if (Quals == Qualifiers::Const) + // We must either select the trivial copy constructor or reach an + // ambiguity; no need to actually perform overload resolution. + return true; + } else if (!Selected) { + return false; + } + // In C++98, we are not supposed to perform overload resolution here, but we + // treat that as a language defect, as suggested on cxx-abi-dev, to treat + // cases like B as having a non-trivial copy constructor: + // struct A { template<typename T> A(T&); }; + // struct B { mutable A a; }; + goto NeedOverloadResolution; + + case Sema::CXXCopyAssignment: + // C++11 [class.copy]p25: + // A copy assignment operator is trivial if: + // - the assignment operator selected to copy each direct [subobject] is + // trivial + if (RD->hasTrivialCopyAssignment()) { + if (Quals == Qualifiers::Const) + return true; + } else if (!Selected) { + return false; + } + // In C++98, we are not supposed to perform overload resolution here, but we + // treat that as a language defect. + goto NeedOverloadResolution; + + case Sema::CXXMoveConstructor: + case Sema::CXXMoveAssignment: + NeedOverloadResolution: + Sema::SpecialMemberOverloadResult *SMOR = + S.LookupSpecialMember(RD, CSM, + Quals & Qualifiers::Const, + Quals & Qualifiers::Volatile, + /*RValueThis*/false, /*ConstThis*/false, + /*VolatileThis*/false); + + // The standard doesn't describe how to behave if the lookup is ambiguous. + // We treat it as not making the member non-trivial, just like the standard + // mandates for the default constructor. This should rarely matter, because + // the member will also be deleted. + if (SMOR->getKind() == Sema::SpecialMemberOverloadResult::Ambiguous) + return true; + + if (!SMOR->getMethod()) { + assert(SMOR->getKind() == + Sema::SpecialMemberOverloadResult::NoMemberOrDeleted); + return false; + } + + // We deliberately don't check if we found a deleted special member. We're + // not supposed to! + if (Selected) + *Selected = SMOR->getMethod(); + return SMOR->getMethod()->isTrivial(); + } + + llvm_unreachable("unknown special method kind"); +} + +static CXXConstructorDecl *findUserDeclaredCtor(CXXRecordDecl *RD) { + for (CXXRecordDecl::ctor_iterator CI = RD->ctor_begin(), CE = RD->ctor_end(); + CI != CE; ++CI) + if (!CI->isImplicit()) + return *CI; + + // Look for constructor templates. + typedef CXXRecordDecl::specific_decl_iterator<FunctionTemplateDecl> tmpl_iter; + for (tmpl_iter TI(RD->decls_begin()), TE(RD->decls_end()); TI != TE; ++TI) { + if (CXXConstructorDecl *CD = + dyn_cast<CXXConstructorDecl>(TI->getTemplatedDecl())) + return CD; + } + + return 0; +} + +/// The kind of subobject we are checking for triviality. The values of this +/// enumeration are used in diagnostics. +enum TrivialSubobjectKind { + /// The subobject is a base class. + TSK_BaseClass, + /// The subobject is a non-static data member. + TSK_Field, + /// The object is actually the complete object. + TSK_CompleteObject +}; + +/// Check whether the special member selected for a given type would be trivial. +static bool checkTrivialSubobjectCall(Sema &S, SourceLocation SubobjLoc, + QualType SubType, + Sema::CXXSpecialMember CSM, + TrivialSubobjectKind Kind, + bool Diagnose) { + CXXRecordDecl *SubRD = SubType->getAsCXXRecordDecl(); + if (!SubRD) + return true; + + CXXMethodDecl *Selected; + if (findTrivialSpecialMember(S, SubRD, CSM, SubType.getCVRQualifiers(), + Diagnose ? &Selected : 0)) + return true; + + if (Diagnose) { + if (!Selected && CSM == Sema::CXXDefaultConstructor) { + S.Diag(SubobjLoc, diag::note_nontrivial_no_def_ctor) + << Kind << SubType.getUnqualifiedType(); + if (CXXConstructorDecl *CD = findUserDeclaredCtor(SubRD)) + S.Diag(CD->getLocation(), diag::note_user_declared_ctor); + } else if (!Selected) + S.Diag(SubobjLoc, diag::note_nontrivial_no_copy) + << Kind << SubType.getUnqualifiedType() << CSM << SubType; + else if (Selected->isUserProvided()) { + if (Kind == TSK_CompleteObject) + S.Diag(Selected->getLocation(), diag::note_nontrivial_user_provided) + << Kind << SubType.getUnqualifiedType() << CSM; + else { + S.Diag(SubobjLoc, diag::note_nontrivial_user_provided) + << Kind << SubType.getUnqualifiedType() << CSM; + S.Diag(Selected->getLocation(), diag::note_declared_at); + } + } else { + if (Kind != TSK_CompleteObject) + S.Diag(SubobjLoc, diag::note_nontrivial_subobject) + << Kind << SubType.getUnqualifiedType() << CSM; + + // Explain why the defaulted or deleted special member isn't trivial. + S.SpecialMemberIsTrivial(Selected, CSM, Diagnose); + } + } + + return false; +} + +/// Check whether the members of a class type allow a special member to be +/// trivial. +static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD, + Sema::CXXSpecialMember CSM, + bool ConstArg, bool Diagnose) { + for (CXXRecordDecl::field_iterator FI = RD->field_begin(), + FE = RD->field_end(); FI != FE; ++FI) { + if (FI->isInvalidDecl() || FI->isUnnamedBitfield()) + continue; + + QualType FieldType = S.Context.getBaseElementType(FI->getType()); + + // Pretend anonymous struct or union members are members of this class. + if (FI->isAnonymousStructOrUnion()) { + if (!checkTrivialClassMembers(S, FieldType->getAsCXXRecordDecl(), + CSM, ConstArg, Diagnose)) + return false; + continue; + } + + // C++11 [class.ctor]p5: + // A default constructor is trivial if [...] + // -- no non-static data member of its class has a + // brace-or-equal-initializer + if (CSM == Sema::CXXDefaultConstructor && FI->hasInClassInitializer()) { + if (Diagnose) + S.Diag(FI->getLocation(), diag::note_nontrivial_in_class_init) << *FI; + return false; + } + + // Objective C ARC 4.3.5: + // [...] nontrivally ownership-qualified types are [...] not trivially + // default constructible, copy constructible, move constructible, copy + // assignable, move assignable, or destructible [...] + if (S.getLangOpts().ObjCAutoRefCount && + FieldType.hasNonTrivialObjCLifetime()) { + if (Diagnose) + S.Diag(FI->getLocation(), diag::note_nontrivial_objc_ownership) + << RD << FieldType.getObjCLifetime(); + return false; + } + + if (ConstArg && !FI->isMutable()) + FieldType.addConst(); + if (!checkTrivialSubobjectCall(S, FI->getLocation(), FieldType, CSM, + TSK_Field, Diagnose)) + return false; + } + + return true; +} + +/// Diagnose why the specified class does not have a trivial special member of +/// the given kind. +void Sema::DiagnoseNontrivial(const CXXRecordDecl *RD, CXXSpecialMember CSM) { + QualType Ty = Context.getRecordType(RD); + if (CSM == CXXCopyConstructor || CSM == CXXCopyAssignment) + Ty.addConst(); + + checkTrivialSubobjectCall(*this, RD->getLocation(), Ty, CSM, + TSK_CompleteObject, /*Diagnose*/true); +} + +/// Determine whether a defaulted or deleted special member function is trivial, +/// as specified in C++11 [class.ctor]p5, C++11 [class.copy]p12, +/// C++11 [class.copy]p25, and C++11 [class.dtor]p5. +bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM, + bool Diagnose) { + assert(!MD->isUserProvided() && CSM != CXXInvalid && "not special enough"); + + CXXRecordDecl *RD = MD->getParent(); + + bool ConstArg = false; + + // C++11 [class.copy]p12, p25: + // A [special member] is trivial if its declared parameter type is the same + // as if it had been implicitly declared [...] + switch (CSM) { + case CXXDefaultConstructor: + case CXXDestructor: + // Trivial default constructors and destructors cannot have parameters. + break; + + case CXXCopyConstructor: + case CXXCopyAssignment: { + // Trivial copy operations always have const, non-volatile parameter types. + ConstArg = true; + const ParmVarDecl *Param0 = MD->getParamDecl(0); + const ReferenceType *RT = Param0->getType()->getAs<ReferenceType>(); + if (!RT || RT->getPointeeType().getCVRQualifiers() != Qualifiers::Const) { + if (Diagnose) + Diag(Param0->getLocation(), diag::note_nontrivial_param_type) + << Param0->getSourceRange() << Param0->getType() + << Context.getLValueReferenceType( + Context.getRecordType(RD).withConst()); + return false; + } + break; + } + + case CXXMoveConstructor: + case CXXMoveAssignment: { + // Trivial move operations always have non-cv-qualified parameters. + const ParmVarDecl *Param0 = MD->getParamDecl(0); + const RValueReferenceType *RT = + Param0->getType()->getAs<RValueReferenceType>(); + if (!RT || RT->getPointeeType().getCVRQualifiers()) { + if (Diagnose) + Diag(Param0->getLocation(), diag::note_nontrivial_param_type) + << Param0->getSourceRange() << Param0->getType() + << Context.getRValueReferenceType(Context.getRecordType(RD)); + return false; + } + break; + } + + case CXXInvalid: + llvm_unreachable("not a special member"); + } + + // FIXME: We require that the parameter-declaration-clause is equivalent to + // that of an implicit declaration, not just that the declared parameter type + // matches, in order to prevent absuridities like a function simultaneously + // being a trivial copy constructor and a non-trivial default constructor. + // This issue has not yet been assigned a core issue number. + if (MD->getMinRequiredArguments() < MD->getNumParams()) { + if (Diagnose) + Diag(MD->getParamDecl(MD->getMinRequiredArguments())->getLocation(), + diag::note_nontrivial_default_arg) + << MD->getParamDecl(MD->getMinRequiredArguments())->getSourceRange(); + return false; + } + if (MD->isVariadic()) { + if (Diagnose) + Diag(MD->getLocation(), diag::note_nontrivial_variadic); + return false; + } + + // C++11 [class.ctor]p5, C++11 [class.dtor]p5: + // A copy/move [constructor or assignment operator] is trivial if + // -- the [member] selected to copy/move each direct base class subobject + // is trivial + // + // C++11 [class.copy]p12, C++11 [class.copy]p25: + // A [default constructor or destructor] is trivial if + // -- all the direct base classes have trivial [default constructors or + // destructors] + for (CXXRecordDecl::base_class_iterator BI = RD->bases_begin(), + BE = RD->bases_end(); BI != BE; ++BI) + if (!checkTrivialSubobjectCall(*this, BI->getLocStart(), + ConstArg ? BI->getType().withConst() + : BI->getType(), + CSM, TSK_BaseClass, Diagnose)) + return false; + + // C++11 [class.ctor]p5, C++11 [class.dtor]p5: + // A copy/move [constructor or assignment operator] for a class X is + // trivial if + // -- for each non-static data member of X that is of class type (or array + // thereof), the constructor selected to copy/move that member is + // trivial + // + // C++11 [class.copy]p12, C++11 [class.copy]p25: + // A [default constructor or destructor] is trivial if + // -- for all of the non-static data members of its class that are of class + // type (or array thereof), each such class has a trivial [default + // constructor or destructor] + if (!checkTrivialClassMembers(*this, RD, CSM, ConstArg, Diagnose)) + return false; + + // C++11 [class.dtor]p5: + // A destructor is trivial if [...] + // -- the destructor is not virtual + if (CSM == CXXDestructor && MD->isVirtual()) { + if (Diagnose) + Diag(MD->getLocation(), diag::note_nontrivial_virtual_dtor) << RD; + return false; + } + + // C++11 [class.ctor]p5, C++11 [class.copy]p12, C++11 [class.copy]p25: + // A [special member] for class X is trivial if [...] + // -- class X has no virtual functions and no virtual base classes + if (CSM != CXXDestructor && MD->getParent()->isDynamicClass()) { + if (!Diagnose) + return false; + + if (RD->getNumVBases()) { + // Check for virtual bases. We already know that the corresponding + // member in all bases is trivial, so vbases must all be direct. + CXXBaseSpecifier &BS = *RD->vbases_begin(); + assert(BS.isVirtual()); + Diag(BS.getLocStart(), diag::note_nontrivial_has_virtual) << RD << 1; + return false; + } + + // Must have a virtual method. + for (CXXRecordDecl::method_iterator MI = RD->method_begin(), + ME = RD->method_end(); MI != ME; ++MI) { + if (MI->isVirtual()) { + SourceLocation MLoc = MI->getLocStart(); + Diag(MLoc, diag::note_nontrivial_has_virtual) << RD << 0; + return false; + } + } + + llvm_unreachable("dynamic class with no vbases and no virtual functions"); + } + + // Looks like it's trivial! + return true; +} + /// \brief Data used with FindHiddenVirtualMethod namespace { struct FindHiddenVirtualMethodData { @@ -4823,9 +5339,9 @@ static bool FindHiddenVirtualMethod(const CXXBaseSpecifier *Specifier, bool foundSameNameMethod = false; SmallVector<CXXMethodDecl *, 8> overloadedMethods; for (Path.Decls = BaseRecord->lookup(Name); - Path.Decls.first != Path.Decls.second; - ++Path.Decls.first) { - NamedDecl *D = *Path.Decls.first; + !Path.Decls.empty(); + Path.Decls = Path.Decls.slice(1)) { + NamedDecl *D = Path.Decls.front(); if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { MD = MD->getCanonicalDecl(); foundSameNameMethod = true; @@ -4877,10 +5393,10 @@ void Sema::DiagnoseHiddenVirtualMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) { // Keep the base methods that were overriden or introduced in the subclass // by 'using' in a set. A base method not in this set is hidden. - for (DeclContext::lookup_result res = DC->lookup(MD->getDeclName()); - res.first != res.second; ++res.first) { - NamedDecl *ND = *res.first; - if (UsingShadowDecl *shad = dyn_cast<UsingShadowDecl>(*res.first)) + DeclContext::lookup_result R = DC->lookup(MD->getDeclName()); + for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; ++I) { + NamedDecl *ND = *I; + if (UsingShadowDecl *shad = dyn_cast<UsingShadowDecl>(*I)) ND = shad->getTargetDecl(); if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(ND)) AddMostOverridenMethods(MD, Data.OverridenAndUsingBaseMethods); @@ -4935,39 +5451,53 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { if (!ClassDecl->hasUserDeclaredConstructor()) ++ASTContext::NumImplicitDefaultConstructors; - if (!ClassDecl->hasUserDeclaredCopyConstructor()) + if (!ClassDecl->hasUserDeclaredCopyConstructor()) { ++ASTContext::NumImplicitCopyConstructors; - if (getLangOpts().CPlusPlus0x && ClassDecl->needsImplicitMoveConstructor()) + // If the properties or semantics of the copy constructor couldn't be + // determined while the class was being declared, force a declaration + // of it now. + if (ClassDecl->needsOverloadResolutionForCopyConstructor()) + DeclareImplicitCopyConstructor(ClassDecl); + } + + if (getLangOpts().CPlusPlus11 && ClassDecl->needsImplicitMoveConstructor()) { ++ASTContext::NumImplicitMoveConstructors; + if (ClassDecl->needsOverloadResolutionForMoveConstructor()) + DeclareImplicitMoveConstructor(ClassDecl); + } + if (!ClassDecl->hasUserDeclaredCopyAssignment()) { ++ASTContext::NumImplicitCopyAssignmentOperators; - - // If we have a dynamic class, then the copy assignment operator may be + + // If we have a dynamic class, then the copy assignment operator may be // virtual, so we have to declare it immediately. This ensures that, e.g., - // it shows up in the right place in the vtable and that we diagnose - // problems with the implicit exception specification. - if (ClassDecl->isDynamicClass()) + // it shows up in the right place in the vtable and that we diagnose + // problems with the implicit exception specification. + if (ClassDecl->isDynamicClass() || + ClassDecl->needsOverloadResolutionForCopyAssignment()) DeclareImplicitCopyAssignment(ClassDecl); } - if (getLangOpts().CPlusPlus0x && ClassDecl->needsImplicitMoveAssignment()) { + if (getLangOpts().CPlusPlus11 && ClassDecl->needsImplicitMoveAssignment()) { ++ASTContext::NumImplicitMoveAssignmentOperators; // Likewise for the move assignment operator. - if (ClassDecl->isDynamicClass()) + if (ClassDecl->isDynamicClass() || + ClassDecl->needsOverloadResolutionForMoveAssignment()) DeclareImplicitMoveAssignment(ClassDecl); } if (!ClassDecl->hasUserDeclaredDestructor()) { ++ASTContext::NumImplicitDestructors; - - // If we have a dynamic class, then the destructor may be virtual, so we + + // If we have a dynamic class, then the destructor may be virtual, so we // have to declare the destructor immediately. This ensures that, e.g., it // shows up in the right place in the vtable and that we diagnose problems // with the implicit exception specification. - if (ClassDecl->isDynamicClass()) + if (ClassDecl->isDynamicClass() || + ClassDecl->needsOverloadResolutionForDestructor()) DeclareImplicitDestructor(ClassDecl); } } @@ -5150,8 +5680,7 @@ QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R, EPI.TypeQuals = 0; EPI.RefQualifier = RQ_None; - return Context.getFunctionType(Context.VoidTy, Proto->arg_type_begin(), - Proto->getNumArgs(), EPI); + return Context.getFunctionType(Context.VoidTy, Proto->getArgTypes(), EPI); } /// CheckConstructor - Checks a fully-formed constructor for @@ -5331,7 +5860,7 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R, EPI.Variadic = false; EPI.TypeQuals = 0; EPI.RefQualifier = RQ_None; - return Context.getFunctionType(Context.VoidTy, 0, 0, EPI); + return Context.getFunctionType(Context.VoidTy, ArrayRef<QualType>(), EPI); } /// CheckConversionDeclarator - Called by ActOnDeclarator to check the @@ -5412,12 +5941,13 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R, // of the errors above fired) and with the conversion type as the // return type. if (D.isInvalidType()) - R = Context.getFunctionType(ConvType, 0, 0, Proto->getExtProtoInfo()); + R = Context.getFunctionType(ConvType, ArrayRef<QualType>(), + Proto->getExtProtoInfo()); // C++0x explicit conversion operators. if (D.getDeclSpec().isExplicitSpecified()) Diag(D.getDeclSpec().getExplicitSpecLoc(), - getLangOpts().CPlusPlus0x ? + getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_explicit_conversion_functions : diag::ext_explicit_conversion_functions) << SourceRange(D.getDeclSpec().getExplicitSpecLoc()); @@ -5551,11 +6081,11 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, Decl::IDNS_Type | Decl::IDNS_Using | Decl::IDNS_Tag | Decl::IDNS_Namespace; NamedDecl *PrevDecl = 0; - for (DeclContext::lookup_result R - = CurContext->getRedeclContext()->lookup(II); - R.first != R.second; ++R.first) { - if ((*R.first)->getIdentifierNamespace() & IDNS) { - PrevDecl = *R.first; + DeclContext::lookup_result R = CurContext->getRedeclContext()->lookup(II); + for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; + ++I) { + if ((*I)->getIdentifierNamespace() & IDNS) { + PrevDecl = *I; break; } } @@ -5978,7 +6508,9 @@ Decl *Sema::ActOnUsingDirective(Scope *S, Diag(IdentLoc, diag::err_expected_namespace_name) << SS.getRange(); } - // FIXME: We ignore attributes for now. + if (UDir) + ProcessDeclAttributeList(S, UDir, AttrList); + return UDir; } @@ -6019,14 +6551,12 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S, case UnqualifiedId::IK_ConstructorTemplateId: // C++11 inheriting constructors. Diag(Name.getLocStart(), - getLangOpts().CPlusPlus0x ? - // FIXME: Produce warn_cxx98_compat_using_decl_constructor - // instead once inheriting constructors work. - diag::err_using_decl_constructor_unsupported : + getLangOpts().CPlusPlus11 ? + diag::warn_cxx98_compat_using_decl_constructor : diag::err_using_decl_constructor) << SS.getRange(); - if (getLangOpts().CPlusPlus0x) break; + if (getLangOpts().CPlusPlus11) break; return 0; @@ -6046,7 +6576,7 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S, if (!TargetName) return 0; - // Warn about using declarations. + // Warn about access declarations. // TODO: store that the declaration was written without 'using' and // talk about access decls instead of using decls in the // diagnostics. @@ -6116,7 +6646,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, // specialization. The UsingShadowDecl in D<T> then points directly // to A::foo, which will look well-formed when we instantiate. // The right solution is to not collapse the shadow-decl chain. - if (!getLangOpts().CPlusPlus0x && CurContext->isRecord()) { + if (!getLangOpts().CPlusPlus11 && CurContext->isRecord()) { DeclContext *OrigDC = Orig->getDeclContext(); // Handle enums and anonymous structs. @@ -6605,7 +7135,7 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc, RequireCompleteDeclContext(const_cast<CXXScopeSpec&>(SS), NamedContext)) return true; - if (getLangOpts().CPlusPlus0x) { + if (getLangOpts().CPlusPlus11) { // C++0x [namespace.udecl]p3: // In a using-declaration used as a member-declaration, the // nested-name-specifier shall name a base class of the class @@ -6694,6 +7224,7 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S, MultiTemplateParamsArg TemplateParamLists, SourceLocation UsingLoc, UnqualifiedId &Name, + AttributeList *AttrList, TypeResult Type) { // Skip up to the relevant declaration scope. while (S->getFlags() & Scope::TemplateParamScope) @@ -6740,6 +7271,8 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S, if (Invalid) NewTD->setInvalidDecl(); + ProcessDeclAttributeList(S, NewTD, AttrList); + CheckTypedefForVariablyModifiedType(S, NewTD); Invalid |= NewTD->isInvalidDecl(); @@ -6969,6 +7502,43 @@ Sema::ComputeDefaultedDefaultCtorExceptionSpec(SourceLocation Loc, return ExceptSpec; } +Sema::ImplicitExceptionSpecification +Sema::ComputeInheritingCtorExceptionSpec(CXXMethodDecl *MD) { + ImplicitExceptionSpecification ExceptSpec(*this); + // FIXME: Compute the exception spec. + return ExceptSpec; +} + +namespace { +/// RAII object to register a special member as being currently declared. +struct DeclaringSpecialMember { + Sema &S; + Sema::SpecialMemberDecl D; + bool WasAlreadyBeingDeclared; + + DeclaringSpecialMember(Sema &S, CXXRecordDecl *RD, Sema::CXXSpecialMember CSM) + : S(S), D(RD, CSM) { + WasAlreadyBeingDeclared = !S.SpecialMembersBeingDeclared.insert(D); + if (WasAlreadyBeingDeclared) + // This almost never happens, but if it does, ensure that our cache + // doesn't contain a stale result. + S.SpecialMemberCache.clear(); + + // FIXME: Register a note to be produced if we encounter an error while + // declaring the special member. + } + ~DeclaringSpecialMember() { + if (!WasAlreadyBeingDeclared) + S.SpecialMembersBeingDeclared.erase(D); + } + + /// \brief Are we already trying to declare this special member? + bool isAlreadyBeingDeclared() const { + return WasAlreadyBeingDeclared; + } +}; +} + CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( CXXRecordDecl *ClassDecl) { // C++ [class.ctor]p5: @@ -6977,9 +7547,13 @@ 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() && + assert(ClassDecl->needsImplicitDefaultConstructor() && "Should not build implicit default constructor!"); + DeclaringSpecialMember DSM(*this, ClassDecl, CXXDefaultConstructor); + if (DSM.isAlreadyBeingDeclared()) + return 0; + bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl, CXXDefaultConstructor, false); @@ -6998,24 +7572,29 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( DefaultCon->setAccess(AS_public); DefaultCon->setDefaulted(); DefaultCon->setImplicit(); - DefaultCon->setTrivial(ClassDecl->hasTrivialDefaultConstructor()); // Build an exception specification pointing back at this constructor. FunctionProtoType::ExtProtoInfo EPI; EPI.ExceptionSpecType = EST_Unevaluated; EPI.ExceptionSpecDecl = DefaultCon; - DefaultCon->setType(Context.getFunctionType(Context.VoidTy, 0, 0, EPI)); + DefaultCon->setType(Context.getFunctionType(Context.VoidTy, + ArrayRef<QualType>(), + EPI)); + + // We don't need to use SpecialMemberIsTrivial here; triviality for default + // constructors is easy to compute. + DefaultCon->setTrivial(ClassDecl->hasTrivialDefaultConstructor()); + + if (ShouldDeleteSpecialMember(DefaultCon, CXXDefaultConstructor)) + SetDeclDeleted(DefaultCon, ClassLoc); // Note that we have declared this constructor. ++ASTContext::NumImplicitDefaultConstructorsDeclared; - + if (Scope *S = getScopeForContext(ClassDecl)) PushOnScopeChains(DefaultCon, S, false); ClassDecl->addDecl(DefaultCon); - if (ShouldDeleteSpecialMember(DefaultCon, CXXDefaultConstructor)) - DefaultCon->setDeletedAsWritten(); - return DefaultCon; } @@ -7031,7 +7610,7 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, SynthesizedFunctionScope Scope(*this, Constructor); DiagnosticErrorTrap Trap(Diags); - if (SetCtorInitializers(Constructor, 0, 0, /*AnyErrors=*/false) || + if (SetCtorInitializers(Constructor, /*AnyErrors=*/false) || Trap.hasErrorOccurred()) { Diag(CurrentLocation, diag::note_member_synthesized_at) << CXXDefaultConstructor << Context.getTagDeclType(ClassDecl); @@ -7051,16 +7630,12 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, } void Sema::ActOnFinishDelayedMemberInitializers(Decl *D) { - if (!D) return; - AdjustDeclIfTemplate(D); - - CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(D); - - if (!ClassDecl->isDependentType()) - CheckExplicitlyDefaultedMethods(ClassDecl); + // Check that any explicitly-defaulted methods have exception specifications + // compatible with their implicit exception specifications. + CheckDelayedExplicitlyDefaultedMemberExceptionSpecs(); } -void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) { +void Sema::DeclareInheritingConstructors(CXXRecordDecl *ClassDecl) { // We start with an initial pass over the base classes to collect those that // inherit constructors from. If there are none, we can forgo all further // processing. @@ -7075,6 +7650,8 @@ void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) { // If we inherit constructors from anything that is dependent, just // abort processing altogether. We'll get another chance for the // instantiations. + // FIXME: We need to ensure that any call to a constructor of this class + // is considered instantiation-dependent in this case. return; } BasesToInheritFrom.push_back(Base->castAs<RecordType>()); @@ -7083,18 +7660,19 @@ void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) { if (BasesToInheritFrom.empty()) return; + // FIXME: Constructor templates. + // Now collect the constructors that we already have in the current class. // Those take precedence over inherited constructors. - // C++0x [class.inhctor]p3: [...] a constructor is implicitly declared [...] + // C++11 [class.inhctor]p3: [...] a constructor is implicitly declared [...] // unless there is a user-declared constructor with the same signature in // the class where the using-declaration appears. llvm::SmallSet<const Type *, 8> ExistingConstructors; for (CXXRecordDecl::ctor_iterator CtorIt = ClassDecl->ctor_begin(), CtorE = ClassDecl->ctor_end(); - CtorIt != CtorE; ++CtorIt) { + CtorIt != CtorE; ++CtorIt) ExistingConstructors.insert( Context.getCanonicalType(CtorIt->getType()).getTypePtr()); - } DeclarationName CreatedCtorName = Context.DeclarationNames.getCXXConstructorName( @@ -7126,62 +7704,71 @@ void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) { SourceLocation UsingLoc = UD ? UD->getLocation() : ClassDecl->getLocation(); - // C++0x [class.inhctor]p1: The candidate set of inherited constructors - // from the class X named in the using-declaration consists of actual - // constructors and notional constructors that result from the - // transformation of defaulted parameters as follows: - // - all non-template default constructors of X, and + // C++11 [class.inhctor]p1: + // The candidate set of inherited constructors from the class X named in + // the using-declaration consists of actual constructors and notional + // constructors that result from the transformation of defaulted + // parameters as follows: + // - all non-template constructors of X, and // - for each non-template constructor of X that has at least one // parameter with a default argument, the set of constructors that // results from omitting any ellipsis parameter specification and // successively omitting parameters with a default argument from the - // end of the parameter-type-list. + // end of the parameter-type-list, and + // FIXME: ...also constructor templates. CXXConstructorDecl *BaseCtor = *CtorIt; bool CanBeCopyOrMove = BaseCtor->isCopyOrMoveConstructor(); const FunctionProtoType *BaseCtorType = BaseCtor->getType()->getAs<FunctionProtoType>(); - for (unsigned params = BaseCtor->getMinRequiredArguments(), - maxParams = BaseCtor->getNumParams(); - params <= maxParams; ++params) { + // Determine whether this would be a copy or move constructor for the + // derived class. + if (BaseCtorType->getNumArgs() >= 1 && + BaseCtorType->getArgType(0)->isReferenceType() && + Context.hasSameUnqualifiedType( + BaseCtorType->getArgType(0)->getPointeeType(), + Context.getTagDeclType(ClassDecl))) + CanBeCopyOrMove = true; + + ArrayRef<QualType> ArgTypes(BaseCtorType->getArgTypes()); + FunctionProtoType::ExtProtoInfo EPI = BaseCtorType->getExtProtoInfo(); + // Core issue (no number yet): the ellipsis is always discarded. + if (EPI.Variadic) { + Diag(UsingLoc, diag::warn_using_decl_constructor_ellipsis); + Diag(BaseCtor->getLocation(), + diag::note_using_decl_constructor_ellipsis); + EPI.Variadic = false; + } + + for (unsigned Params = BaseCtor->getMinRequiredArguments(), + MaxParams = BaseCtor->getNumParams(); + Params <= MaxParams; ++Params) { // Skip default constructors. They're never inherited. - if (params == 0) + if (Params == 0) continue; - // Skip copy and move constructors for the same reason. - if (CanBeCopyOrMove && params == 1) + + // Skip copy and move constructors for both base and derived class + // for the same reason. + if (CanBeCopyOrMove && Params == 1) continue; // Build up a function type for this particular constructor. - // FIXME: The working paper does not consider that the exception spec - // for the inheriting constructor might be larger than that of the - // source. This code doesn't yet, either. When it does, this code will - // need to be delayed until after exception specifications and in-class - // member initializers are attached. - const Type *NewCtorType; - if (params == maxParams) - NewCtorType = BaseCtorType; - else { - SmallVector<QualType, 16> Args; - for (unsigned i = 0; i < params; ++i) { - Args.push_back(BaseCtorType->getArgType(i)); - } - FunctionProtoType::ExtProtoInfo ExtInfo = - BaseCtorType->getExtProtoInfo(); - ExtInfo.Variadic = false; - NewCtorType = Context.getFunctionType(BaseCtorType->getResultType(), - Args.data(), params, ExtInfo) - .getTypePtr(); - } + QualType NewCtorType = + Context.getFunctionType(Context.VoidTy, ArgTypes.slice(0, Params), + EPI); const Type *CanonicalNewCtorType = - Context.getCanonicalType(NewCtorType); + Context.getCanonicalType(NewCtorType).getTypePtr(); - // Now that we have the type, first check if the class already has a - // constructor with this signature. + // C++11 [class.inhctor]p3: + // ... a constructor is implicitly declared with the same constructor + // characteristics unless there is a user-declared constructor with + // the same signature in the class where the using-declaration appears if (ExistingConstructors.count(CanonicalNewCtorType)) continue; - // Then we check if we have already declared an inherited constructor - // with this signature. + // C++11 [class.inhctor]p7: + // If two using-declarations declare inheriting constructors with the + // same signature, the program is ill-formed std::pair<ConstructorToSourceMap::iterator, bool> result = InheritedConstructors.insert(std::make_pair( CanonicalNewCtorType, @@ -7203,35 +7790,47 @@ void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) { diag::note_using_decl_constructor_conflict_previous_ctor); Diag(PrevCtor->getLocation(), diag::note_using_decl_constructor_conflict_previous_using); + } else { + // Core issue (no number): if the same inheriting constructor is + // produced by multiple base class constructors from the same base + // class, the inheriting constructor is defined as deleted. + SetDeclDeleted(result.first->second.second, UsingLoc); } continue; } // OK, we're there, now add the constructor. - // C++0x [class.inhctor]p8: [...] that would be performed by a - // user-written inline constructor [...] DeclarationNameInfo DNI(CreatedCtorName, UsingLoc); CXXConstructorDecl *NewCtor = CXXConstructorDecl::Create( - Context, ClassDecl, UsingLoc, DNI, QualType(NewCtorType, 0), + Context, ClassDecl, UsingLoc, DNI, NewCtorType, /*TInfo=*/0, BaseCtor->isExplicit(), /*Inline=*/true, - /*ImplicitlyDeclared=*/true, - // FIXME: Due to a defect in the standard, we treat inherited - // constructors as constexpr even if that makes them ill-formed. - /*Constexpr=*/BaseCtor->isConstexpr()); + /*ImplicitlyDeclared=*/true, /*Constexpr=*/BaseCtor->isConstexpr()); NewCtor->setAccess(BaseCtor->getAccess()); + // Build an unevaluated exception specification for this constructor. + EPI.ExceptionSpecType = EST_Unevaluated; + EPI.ExceptionSpecDecl = NewCtor; + NewCtor->setType(Context.getFunctionType(Context.VoidTy, + ArgTypes.slice(0, Params), + EPI)); + // Build up the parameter decls and add them. SmallVector<ParmVarDecl *, 16> ParamDecls; - for (unsigned i = 0; i < params; ++i) { - ParamDecls.push_back(ParmVarDecl::Create(Context, NewCtor, - UsingLoc, UsingLoc, - /*IdentifierInfo=*/0, - BaseCtorType->getArgType(i), - /*TInfo=*/0, SC_None, - SC_None, /*DefaultArg=*/0)); + for (unsigned i = 0; i < Params; ++i) { + ParmVarDecl *PD = ParmVarDecl::Create(Context, NewCtor, + UsingLoc, UsingLoc, + /*IdentifierInfo=*/0, + BaseCtorType->getArgType(i), + /*TInfo=*/0, SC_None, + /*DefaultArg=*/0); + PD->setScopeInfo(0, i); + PD->setImplicit(); + ParamDecls.push_back(PD); } NewCtor->setParams(ParamDecls); NewCtor->setInheritedConstructor(BaseCtor); + if (BaseCtor->isDeleted()) + SetDeclDeleted(NewCtor, UsingLoc); ClassDecl->addDecl(NewCtor); result.first->second.second = NewCtor; @@ -7240,6 +7839,35 @@ void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) { } } +void Sema::DefineInheritingConstructor(SourceLocation CurrentLocation, + CXXConstructorDecl *Constructor) { + CXXRecordDecl *ClassDecl = Constructor->getParent(); + assert(Constructor->getInheritedConstructor() && + !Constructor->doesThisDeclarationHaveABody() && + !Constructor->isDeleted()); + + SynthesizedFunctionScope Scope(*this, Constructor); + DiagnosticErrorTrap Trap(Diags); + if (SetCtorInitializers(Constructor, /*AnyErrors=*/false) || + Trap.hasErrorOccurred()) { + Diag(CurrentLocation, diag::note_inhctor_synthesized_at) + << Context.getTagDeclType(ClassDecl); + Constructor->setInvalidDecl(); + return; + } + + SourceLocation Loc = Constructor->getLocation(); + Constructor->setBody(new (Context) CompoundStmt(Loc)); + + Constructor->setUsed(); + MarkVTableUsed(CurrentLocation, ClassDecl); + + if (ASTMutationListener *L = getASTMutationListener()) { + L->CompletedImplicitDefinition(Constructor); + } +} + + Sema::ImplicitExceptionSpecification Sema::ComputeDefaultedDtorExceptionSpec(CXXMethodDecl *MD) { CXXRecordDecl *ClassDecl = MD->getParent(); @@ -7290,6 +7918,11 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) { // If a class has no user-declared destructor, a destructor is // declared implicitly. An implicitly-declared destructor is an // inline public member of its class. + assert(ClassDecl->needsImplicitDestructor()); + + DeclaringSpecialMember DSM(*this, ClassDecl, CXXDestructor); + if (DSM.isAlreadyBeingDeclared()) + return 0; // Create the actual destructor declaration. CanQualType ClassType @@ -7305,13 +7938,23 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) { Destructor->setAccess(AS_public); Destructor->setDefaulted(); Destructor->setImplicit(); - Destructor->setTrivial(ClassDecl->hasTrivialDestructor()); // Build an exception specification pointing back at this destructor. FunctionProtoType::ExtProtoInfo EPI; EPI.ExceptionSpecType = EST_Unevaluated; EPI.ExceptionSpecDecl = Destructor; - Destructor->setType(Context.getFunctionType(Context.VoidTy, 0, 0, EPI)); + Destructor->setType(Context.getFunctionType(Context.VoidTy, + ArrayRef<QualType>(), + EPI)); + + AddOverriddenMethods(ClassDecl, Destructor); + + // We don't need to use SpecialMemberIsTrivial here; triviality for + // destructors is easy to compute. + Destructor->setTrivial(ClassDecl->hasTrivialDestructor()); + + if (ShouldDeleteSpecialMember(Destructor, CXXDestructor)) + SetDeclDeleted(Destructor, ClassLoc); // Note that we have declared this destructor. ++ASTContext::NumImplicitDestructorsDeclared; @@ -7321,11 +7964,6 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) { PushOnScopeChains(Destructor, S, false); ClassDecl->addDecl(Destructor); - AddOverriddenMethods(ClassDecl, Destructor); - - if (ShouldDeleteSpecialMember(Destructor, CXXDestructor)) - Destructor->setDeletedAsWritten(); - return Destructor; } @@ -7369,6 +8007,14 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation, /// \brief Perform any semantic analysis which needs to be delayed until all /// pending class member declarations have been parsed. void Sema::ActOnFinishCXXMemberDecls() { + // If the context is an invalid C++ class, just suppress these checks. + if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(CurContext)) { + if (Record->isInvalidDecl()) { + DelayedDestructorExceptionSpecChecks.clear(); + return; + } + } + // Perform any deferred checking of exception specifications for virtual // destructors. for (unsigned i = 0, e = DelayedDestructorExceptionSpecChecks.size(); @@ -7385,7 +8031,7 @@ void Sema::ActOnFinishCXXMemberDecls() { void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl, CXXDestructorDecl *Destructor) { - assert(getLangOpts().CPlusPlus0x && + assert(getLangOpts().CPlusPlus11 && "adjusting dtor exception specs was introduced in c++11"); // C++11 [class.dtor]p3: @@ -7403,7 +8049,9 @@ void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl, FunctionProtoType::ExtProtoInfo EPI = DtorType->getExtProtoInfo(); EPI.ExceptionSpecType = EST_Unevaluated; EPI.ExceptionSpecDecl = Destructor; - Destructor->setType(Context.getFunctionType(Context.VoidTy, 0, 0, EPI)); + Destructor->setType(Context.getFunctionType(Context.VoidTy, + ArrayRef<QualType>(), + EPI)); // FIXME: If the destructor has a body that could throw, and the newly created // spec doesn't allow exceptions, we should emit a warning, because this @@ -7412,6 +8060,60 @@ void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl, // needs to be done somewhere else. } +/// When generating a defaulted copy or move assignment operator, if a field +/// should be copied with __builtin_memcpy rather than via explicit assignments, +/// do so. This optimization only applies for arrays of scalars, and for arrays +/// of class type where the selected copy/move-assignment operator is trivial. +static StmtResult +buildMemcpyForAssignmentOp(Sema &S, SourceLocation Loc, QualType T, + Expr *To, Expr *From) { + // Compute the size of the memory buffer to be copied. + QualType SizeType = S.Context.getSizeType(); + llvm::APInt Size(S.Context.getTypeSize(SizeType), + S.Context.getTypeSizeInChars(T).getQuantity()); + + // Take the address of the field references for "from" and "to". We + // directly construct UnaryOperators here because semantic analysis + // does not permit us to take the address of an xvalue. + From = new (S.Context) UnaryOperator(From, UO_AddrOf, + S.Context.getPointerType(From->getType()), + VK_RValue, OK_Ordinary, Loc); + To = new (S.Context) UnaryOperator(To, UO_AddrOf, + S.Context.getPointerType(To->getType()), + VK_RValue, OK_Ordinary, Loc); + + const Type *E = T->getBaseElementTypeUnsafe(); + bool NeedsCollectableMemCpy = + E->isRecordType() && E->getAs<RecordType>()->getDecl()->hasObjectMember(); + + // Create a reference to the __builtin_objc_memmove_collectable function + StringRef MemCpyName = NeedsCollectableMemCpy ? + "__builtin_objc_memmove_collectable" : + "__builtin_memcpy"; + LookupResult R(S, &S.Context.Idents.get(MemCpyName), Loc, + Sema::LookupOrdinaryName); + S.LookupName(R, S.TUScope, true); + + FunctionDecl *MemCpy = R.getAsSingle<FunctionDecl>(); + if (!MemCpy) + // Something went horribly wrong earlier, and we will have complained + // about it. + return StmtError(); + + ExprResult MemCpyRef = S.BuildDeclRefExpr(MemCpy, S.Context.BuiltinFnTy, + VK_RValue, Loc, 0); + assert(MemCpyRef.isUsable() && "Builtin reference cannot fail"); + + Expr *CallArgs[] = { + To, From, IntegerLiteral::Create(S.Context, Size, SizeType, Loc) + }; + ExprResult Call = S.ActOnCallExpr(/*Scope=*/0, MemCpyRef.take(), + Loc, CallArgs, Loc); + + assert(!Call.isInvalid() && "Call to __builtin_memcpy cannot fail!"); + return S.Owned(Call.takeAs<Stmt>()); +} + /// \brief Builds a statement that copies/moves the given entity from \p From to /// \c To. /// @@ -7437,13 +8139,14 @@ void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl, /// /// \param Depth Internal parameter recording the depth of the recursion. /// -/// \returns A statement or a loop that copies the expressions. +/// \returns A statement or a loop that copies the expressions, or StmtResult(0) +/// if a memcpy should be used instead. static StmtResult -BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, - Expr *To, Expr *From, - bool CopyingBaseSubobject, bool Copying, - unsigned Depth = 0) { - // C++0x [class.copy]p28: +buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T, + Expr *To, Expr *From, + bool CopyingBaseSubobject, bool Copying, + unsigned Depth = 0) { + // C++11 [class.copy]p28: // Each subobject is assigned in the manner appropriate to its type: // // - if the subobject is of class type, as if by a call to operator= with @@ -7451,32 +8154,41 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, // subobject of x as a single function argument (as if by explicit // qualification; that is, ignoring any possible virtual overriding // functions in more derived classes); + // + // C++03 [class.copy]p13: + // - if the subobject is of class type, the copy assignment operator for + // the class is used (as if by explicit qualification; that is, + // ignoring any possible virtual overriding functions in more derived + // classes); if (const RecordType *RecordTy = T->getAs<RecordType>()) { CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(RecordTy->getDecl()); - + // Look for operator=. DeclarationName Name = S.Context.DeclarationNames.getCXXOperatorName(OO_Equal); LookupResult OpLookup(S, Name, Loc, Sema::LookupOrdinaryName); S.LookupQualifiedName(OpLookup, ClassDecl, false); - - // Filter out any result that isn't a copy/move-assignment operator. - LookupResult::Filter F = OpLookup.makeFilter(); - while (F.hasNext()) { - NamedDecl *D = F.next(); - if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) - if (Method->isCopyAssignmentOperator() || - (!Copying && Method->isMoveAssignmentOperator())) - continue; - F.erase(); + // Prior to C++11, filter out any result that isn't a copy/move-assignment + // operator. + if (!S.getLangOpts().CPlusPlus11) { + LookupResult::Filter F = OpLookup.makeFilter(); + while (F.hasNext()) { + NamedDecl *D = F.next(); + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) + if (Method->isCopyAssignmentOperator() || + (!Copying && Method->isMoveAssignmentOperator())) + continue; + + F.erase(); + } + F.done(); } - F.done(); - + // Suppress the protected check (C++ [class.protected]) for each of the - // assignment operators we found. This strange dance is required when + // assignment operators we found. This strange dance is required when // we're assigning via a base classes's copy-assignment operator. To - // ensure that we're getting the right base class subobject (without + // ensure that we're getting the right base class subobject (without // ambiguities), we need to cast "this" to that subobject type; to // ensure that we don't go through the virtual call mechanism, we need // to qualify the operator= name with the base class (see below). However, @@ -7491,20 +8203,20 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, L.setAccess(AS_public); } } - + // Create the nested-name-specifier that will be used to qualify the // reference to operator=; this is required to suppress the virtual // call mechanism. CXXScopeSpec SS; const Type *CanonicalT = S.Context.getCanonicalType(T.getTypePtr()); - SS.MakeTrivial(S.Context, - NestedNameSpecifier::Create(S.Context, 0, false, + SS.MakeTrivial(S.Context, + NestedNameSpecifier::Create(S.Context, 0, false, CanonicalT), Loc); - + // Create the reference to operator=. ExprResult OpEqualRef - = S.BuildMemberReferenceExpr(To, T, Loc, /*isArrow=*/false, SS, + = S.BuildMemberReferenceExpr(To, T, Loc, /*isArrow=*/false, SS, /*TemplateKWLoc=*/SourceLocation(), /*FirstQualifierInScope=*/0, OpLookup, @@ -7512,39 +8224,46 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, /*SuppressQualifierCheck=*/true); if (OpEqualRef.isInvalid()) return StmtError(); - + // Build the call to the assignment operator. - ExprResult Call = S.BuildCallToMemberFunction(/*Scope=*/0, + ExprResult Call = S.BuildCallToMemberFunction(/*Scope=*/0, OpEqualRef.takeAs<Expr>(), Loc, &From, 1, Loc); if (Call.isInvalid()) return StmtError(); - - return S.Owned(Call.takeAs<Stmt>()); + + // If we built a call to a trivial 'operator=' while copying an array, + // bail out. We'll replace the whole shebang with a memcpy. + CXXMemberCallExpr *CE = dyn_cast<CXXMemberCallExpr>(Call.get()); + if (CE && CE->getMethodDecl()->isTrivial() && Depth) + return StmtResult((Stmt*)0); + + // Convert to an expression-statement, and clean up any produced + // temporaries. + return S.ActOnExprStmt(Call); } - // - if the subobject is of scalar type, the built-in assignment + // - if the subobject is of scalar type, the built-in assignment // operator is used. - const ConstantArrayType *ArrayTy = S.Context.getAsConstantArrayType(T); + const ConstantArrayType *ArrayTy = S.Context.getAsConstantArrayType(T); if (!ArrayTy) { ExprResult Assignment = S.CreateBuiltinBinOp(Loc, BO_Assign, To, From); if (Assignment.isInvalid()) return StmtError(); - - return S.Owned(Assignment.takeAs<Stmt>()); + return S.ActOnExprStmt(Assignment); } - - // - if the subobject is an array, each element is assigned, in the + + // - if the subobject is an array, each element is assigned, in the // manner appropriate to the element type; - + // Construct a loop over the array bounds, e.g., // // for (__SIZE_TYPE__ i0 = 0; i0 != array-size; ++i0) // // that will copy each of the array elements. QualType SizeType = S.Context.getSizeType(); - + // Create the iteration variable. IdentifierInfo *IterationVarName = 0; { @@ -7556,8 +8275,8 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, VarDecl *IterationVar = VarDecl::Create(S.Context, S.CurContext, Loc, Loc, IterationVarName, SizeType, S.Context.getTrivialTypeSourceInfo(SizeType, Loc), - SC_None, SC_None); - + SC_None); + // Initialize the iteration variable to zero. llvm::APInt Zero(S.Context.getTypeSize(SizeType), 0); IterationVar->setInit(IntegerLiteral::Create(S.Context, Zero, SizeType, Loc)); @@ -7572,7 +8291,26 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, // Create the DeclStmt that holds the iteration variable. Stmt *InitStmt = new (S.Context) DeclStmt(DeclGroupRef(IterationVar),Loc,Loc); - + + // Subscript the "from" and "to" expressions with the iteration variable. + From = AssertSuccess(S.CreateBuiltinArraySubscriptExpr(From, Loc, + IterationVarRefRVal, + Loc)); + To = AssertSuccess(S.CreateBuiltinArraySubscriptExpr(To, Loc, + IterationVarRefRVal, + Loc)); + if (!Copying) // Cast to rvalue + From = CastForMoving(S, From); + + // Build the copy/move for an individual element of the array. + StmtResult Copy = + buildSingleCopyAssignRecursively(S, Loc, ArrayTy->getElementType(), + To, From, CopyingBaseSubobject, + Copying, Depth + 1); + // Bail out if copying fails or if we determined that we should use memcpy. + if (Copy.isInvalid() || !Copy.get()) + return Copy; + // Create the comparison against the array bound. llvm::APInt Upper = ArrayTy->getSize().zextOrTrunc(S.Context.getTypeSize(SizeType)); @@ -7581,104 +8319,38 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, IntegerLiteral::Create(S.Context, Upper, SizeType, Loc), BO_NE, S.Context.BoolTy, VK_RValue, OK_Ordinary, Loc, false); - + // Create the pre-increment of the iteration variable. Expr *Increment = new (S.Context) UnaryOperator(IterationVarRef, UO_PreInc, SizeType, VK_LValue, OK_Ordinary, Loc); - - // Subscript the "from" and "to" expressions with the iteration variable. - From = AssertSuccess(S.CreateBuiltinArraySubscriptExpr(From, Loc, - IterationVarRefRVal, - Loc)); - To = AssertSuccess(S.CreateBuiltinArraySubscriptExpr(To, Loc, - IterationVarRefRVal, - Loc)); - if (!Copying) // Cast to rvalue - From = CastForMoving(S, From); - // Build the copy/move for an individual element of the array. - StmtResult Copy = BuildSingleCopyAssign(S, Loc, ArrayTy->getElementType(), - To, From, CopyingBaseSubobject, - Copying, Depth + 1); - if (Copy.isInvalid()) - return StmtError(); - // Construct the loop that copies all elements of this array. return S.ActOnForStmt(Loc, Loc, InitStmt, S.MakeFullExpr(Comparison), - 0, S.MakeFullExpr(Increment), + 0, S.MakeFullDiscardedValueExpr(Increment), Loc, Copy.take()); } -/// Determine whether an implicit copy assignment operator for ClassDecl has a -/// const argument. -/// FIXME: It ought to be possible to store this on the record. -static bool isImplicitCopyAssignmentArgConst(Sema &S, - CXXRecordDecl *ClassDecl) { - if (ClassDecl->isInvalidDecl()) - return true; +static StmtResult +buildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, + Expr *To, Expr *From, + bool CopyingBaseSubobject, bool Copying) { + // Maybe we should use a memcpy? + if (T->isArrayType() && !T.isConstQualified() && !T.isVolatileQualified() && + T.isTriviallyCopyableType(S.Context)) + return buildMemcpyForAssignmentOp(S, Loc, T, To, From); - // C++ [class.copy]p10: - // If the class definition does not explicitly declare a copy - // assignment operator, one is declared implicitly. - // The implicitly-defined copy assignment operator for a class X - // will have the form - // - // X& X::operator=(const X&) - // - // if - // -- each direct base class B of X has a copy assignment operator - // whose parameter is of type const B&, const volatile B& or B, - // and - for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), - BaseEnd = ClassDecl->bases_end(); - Base != BaseEnd; ++Base) { - // We'll handle this below - if (S.getLangOpts().CPlusPlus0x && Base->isVirtual()) - continue; + StmtResult Result(buildSingleCopyAssignRecursively(S, Loc, T, To, From, + CopyingBaseSubobject, + Copying, 0)); - assert(!Base->getType()->isDependentType() && - "Cannot generate implicit members for class with dependent bases."); - CXXRecordDecl *BaseClassDecl = Base->getType()->getAsCXXRecordDecl(); - if (!S.LookupCopyingAssignment(BaseClassDecl, Qualifiers::Const, false, 0)) - return false; - } + // If we ended up picking a trivial assignment operator for an array of a + // non-trivially-copyable class type, just emit a memcpy. + if (!Result.isInvalid() && !Result.get()) + return buildMemcpyForAssignmentOp(S, Loc, T, To, From); - // In C++11, the above citation has "or virtual" added - if (S.getLangOpts().CPlusPlus0x) { - for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(), - BaseEnd = ClassDecl->vbases_end(); - Base != BaseEnd; ++Base) { - assert(!Base->getType()->isDependentType() && - "Cannot generate implicit members for class with dependent bases."); - CXXRecordDecl *BaseClassDecl = Base->getType()->getAsCXXRecordDecl(); - if (!S.LookupCopyingAssignment(BaseClassDecl, Qualifiers::Const, - false, 0)) - return false; - } - } - - // -- for all the nonstatic data members of X that are of a class - // type M (or array thereof), each such class type has a copy - // assignment operator whose parameter is of type const M&, - // const volatile M& or M. - for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), - FieldEnd = ClassDecl->field_end(); - Field != FieldEnd; ++Field) { - QualType FieldType = S.Context.getBaseElementType(Field->getType()); - if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) - if (!S.LookupCopyingAssignment(FieldClassDecl, Qualifiers::Const, - false, 0)) - return false; - } - - // Otherwise, the implicitly declared copy assignment operator will - // have the form - // - // X& X::operator=(X&) - - return true; + return Result; } Sema::ImplicitExceptionSpecification @@ -7748,10 +8420,15 @@ 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. + assert(ClassDecl->needsImplicitCopyAssignment()); + + DeclaringSpecialMember DSM(*this, ClassDecl, CXXCopyAssignment); + if (DSM.isAlreadyBeingDeclared()) + return 0; QualType ArgType = Context.getTypeDeclType(ClassDecl); QualType RetType = Context.getLValueReferenceType(ArgType); - if (isImplicitCopyAssignmentArgConst(*this, ClassDecl)) + if (ClassDecl->implicitCopyAssignmentHasConstParam()) ArgType = ArgType.withConst(); ArgType = Context.getLValueReferenceType(ArgType); @@ -7762,45 +8439,49 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { DeclarationNameInfo NameInfo(Name, ClassLoc); CXXMethodDecl *CopyAssignment = CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(), - /*TInfo=*/0, /*isStatic=*/false, - /*StorageClassAsWritten=*/SC_None, + /*TInfo=*/0, + /*StorageClass=*/SC_None, /*isInline=*/true, /*isConstexpr=*/false, SourceLocation()); CopyAssignment->setAccess(AS_public); CopyAssignment->setDefaulted(); CopyAssignment->setImplicit(); - CopyAssignment->setTrivial(ClassDecl->hasTrivialCopyAssignment()); // Build an exception specification pointing back at this member. FunctionProtoType::ExtProtoInfo EPI; EPI.ExceptionSpecType = EST_Unevaluated; EPI.ExceptionSpecDecl = CopyAssignment; - CopyAssignment->setType(Context.getFunctionType(RetType, &ArgType, 1, EPI)); + CopyAssignment->setType(Context.getFunctionType(RetType, ArgType, EPI)); // Add the parameter to the operator. ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyAssignment, ClassLoc, ClassLoc, /*Id=*/0, ArgType, /*TInfo=*/0, - SC_None, SC_None, 0); CopyAssignment->setParams(FromParam); - - // Note that we have added this copy-assignment operator. - ++ASTContext::NumImplicitCopyAssignmentOperatorsDeclared; - if (Scope *S = getScopeForContext(ClassDecl)) - PushOnScopeChains(CopyAssignment, S, false); - ClassDecl->addDecl(CopyAssignment); - + AddOverriddenMethods(ClassDecl, CopyAssignment); + + CopyAssignment->setTrivial( + ClassDecl->needsOverloadResolutionForCopyAssignment() + ? SpecialMemberIsTrivial(CopyAssignment, CXXCopyAssignment) + : ClassDecl->hasTrivialCopyAssignment()); + // C++0x [class.copy]p19: // .... If the class definition does not explicitly declare a copy // assignment operator, there is no user-declared move constructor, and // there is no user-declared move assignment operator, a copy assignment // operator is implicitly declared as defaulted. if (ShouldDeleteSpecialMember(CopyAssignment, CXXCopyAssignment)) - CopyAssignment->setDeletedAsWritten(); + SetDeclDeleted(CopyAssignment, ClassLoc); + + // Note that we have added this copy-assignment operator. + ++ASTContext::NumImplicitCopyAssignmentOperatorsDeclared; + + if (Scope *S = getScopeForContext(ClassDecl)) + PushOnScopeChains(CopyAssignment, S, false); + ClassDecl->addDecl(CopyAssignment); - AddOverriddenMethods(ClassDecl, CopyAssignment); return CopyAssignment; } @@ -7892,7 +8573,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, VK_LValue, &BasePath); // Build the copy. - StmtResult Copy = BuildSingleCopyAssign(*this, Loc, BaseType, + StmtResult Copy = buildSingleCopyAssign(*this, Loc, BaseType, To.get(), From, /*CopyingBaseSubobject=*/true, /*Copying=*/true); @@ -7907,11 +8588,6 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, Statements.push_back(Copy.takeAs<Expr>()); } - // \brief Reference to the __builtin_memcpy function. - Expr *BuiltinMemCpyRef = 0; - // \brief Reference to the __builtin_objc_memmove_collectable function. - Expr *CollectableMemCpyRef = 0; - // Assign non-static members. for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), FieldEnd = ClassDecl->field_end(); @@ -7969,99 +8645,9 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, MemberLookup, 0); assert(!From.isInvalid() && "Implicit field reference cannot fail"); assert(!To.isInvalid() && "Implicit field reference cannot fail"); - - // If the field should be copied with __builtin_memcpy rather than via - // explicit assignments, do so. This optimization only applies for arrays - // of scalars and arrays of class type with trivial copy-assignment - // operators. - if (FieldType->isArrayType() && !FieldType.isVolatileQualified() - && BaseType.hasTrivialAssignment(Context, /*Copying=*/true)) { - // Compute the size of the memory buffer to be copied. - QualType SizeType = Context.getSizeType(); - llvm::APInt Size(Context.getTypeSize(SizeType), - Context.getTypeSizeInChars(BaseType).getQuantity()); - for (const ConstantArrayType *Array - = Context.getAsConstantArrayType(FieldType); - Array; - Array = Context.getAsConstantArrayType(Array->getElementType())) { - llvm::APInt ArraySize - = Array->getSize().zextOrTrunc(Size.getBitWidth()); - Size *= ArraySize; - } - - // Take the address of the field references for "from" and "to". - From = CreateBuiltinUnaryOp(Loc, UO_AddrOf, From.get()); - To = CreateBuiltinUnaryOp(Loc, UO_AddrOf, To.get()); - - bool NeedsCollectableMemCpy = - (BaseType->isRecordType() && - BaseType->getAs<RecordType>()->getDecl()->hasObjectMember()); - - if (NeedsCollectableMemCpy) { - if (!CollectableMemCpyRef) { - // Create a reference to the __builtin_objc_memmove_collectable function. - LookupResult R(*this, - &Context.Idents.get("__builtin_objc_memmove_collectable"), - Loc, LookupOrdinaryName); - LookupName(R, TUScope, true); - - FunctionDecl *CollectableMemCpy = R.getAsSingle<FunctionDecl>(); - if (!CollectableMemCpy) { - // Something went horribly wrong earlier, and we will have - // complained about it. - Invalid = true; - continue; - } - - CollectableMemCpyRef = BuildDeclRefExpr(CollectableMemCpy, - Context.BuiltinFnTy, - VK_RValue, Loc, 0).take(); - assert(CollectableMemCpyRef && "Builtin reference cannot fail"); - } - } - // Create a reference to the __builtin_memcpy builtin function. - else if (!BuiltinMemCpyRef) { - LookupResult R(*this, &Context.Idents.get("__builtin_memcpy"), Loc, - LookupOrdinaryName); - LookupName(R, TUScope, true); - - FunctionDecl *BuiltinMemCpy = R.getAsSingle<FunctionDecl>(); - if (!BuiltinMemCpy) { - // Something went horribly wrong earlier, and we will have complained - // about it. - Invalid = true; - continue; - } - BuiltinMemCpyRef = BuildDeclRefExpr(BuiltinMemCpy, - Context.BuiltinFnTy, - VK_RValue, Loc, 0).take(); - assert(BuiltinMemCpyRef && "Builtin reference cannot fail"); - } - - SmallVector<Expr*, 8> CallArgs; - CallArgs.push_back(To.takeAs<Expr>()); - CallArgs.push_back(From.takeAs<Expr>()); - CallArgs.push_back(IntegerLiteral::Create(Context, Size, SizeType, Loc)); - ExprResult Call = ExprError(); - if (NeedsCollectableMemCpy) - Call = ActOnCallExpr(/*Scope=*/0, - CollectableMemCpyRef, - Loc, CallArgs, - Loc); - else - Call = ActOnCallExpr(/*Scope=*/0, - BuiltinMemCpyRef, - Loc, CallArgs, - Loc); - - assert(!Call.isInvalid() && "Call to __builtin_memcpy cannot fail!"); - Statements.push_back(Call.takeAs<Expr>()); - continue; - } - // Build the copy of this field. - StmtResult Copy = BuildSingleCopyAssign(*this, Loc, FieldType, + StmtResult Copy = buildSingleCopyAssign(*this, Loc, FieldType, To.get(), From.get(), /*CopyingBaseSubobject=*/false, /*Copying=*/true); @@ -8188,10 +8774,7 @@ hasVirtualBaseWithNonTrivialMoveAssignment(Sema &S, CXXRecordDecl *ClassDecl) { if (BaseClass->needsImplicitMoveAssignment()) S.DeclareImplicitMoveAssignment(BaseClass); - // If the class has both a trivial move assignment and a non-trivial move - // assignment, hasTrivialMoveAssignment() is false. - if (BaseClass->hasDeclaredMoveAssignment() && - !BaseClass->hasTrivialMoveAssignment()) + if (BaseClass->hasNonTrivialMoveAssignment()) return true; } @@ -8215,14 +8798,18 @@ hasMoveOrIsTriviallyCopyable(Sema &S, QualType Type, bool IsConstructor) { return true; if (IsConstructor) { + // FIXME: Need this because otherwise hasMoveConstructor isn't guaranteed to + // give the right answer. if (ClassDecl->needsImplicitMoveConstructor()) S.DeclareImplicitMoveConstructor(ClassDecl); - return ClassDecl->hasDeclaredMoveConstructor(); + return ClassDecl->hasMoveConstructor(); } + // FIXME: Need this because otherwise hasMoveAssignment isn't guaranteed to + // give the right answer. if (ClassDecl->needsImplicitMoveAssignment()) S.DeclareImplicitMoveAssignment(ClassDecl); - return ClassDecl->hasDeclaredMoveAssignment(); + return ClassDecl->hasMoveAssignment(); } /// Determine whether all non-static data members and direct or virtual bases @@ -8266,6 +8853,10 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) { // - [first 4 bullets] assert(ClassDecl->needsImplicitMoveAssignment()); + DeclaringSpecialMember DSM(*this, ClassDecl, CXXMoveAssignment); + if (DSM.isAlreadyBeingDeclared()) + return 0; + // [Checked after we build the declaration] // - the move assignment operator would not be implicitly defined as // deleted, @@ -8296,32 +8887,34 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) { DeclarationNameInfo NameInfo(Name, ClassLoc); CXXMethodDecl *MoveAssignment = CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(), - /*TInfo=*/0, /*isStatic=*/false, - /*StorageClassAsWritten=*/SC_None, + /*TInfo=*/0, + /*StorageClass=*/SC_None, /*isInline=*/true, /*isConstexpr=*/false, SourceLocation()); MoveAssignment->setAccess(AS_public); MoveAssignment->setDefaulted(); MoveAssignment->setImplicit(); - MoveAssignment->setTrivial(ClassDecl->hasTrivialMoveAssignment()); // Build an exception specification pointing back at this member. FunctionProtoType::ExtProtoInfo EPI; EPI.ExceptionSpecType = EST_Unevaluated; EPI.ExceptionSpecDecl = MoveAssignment; - MoveAssignment->setType(Context.getFunctionType(RetType, &ArgType, 1, EPI)); + MoveAssignment->setType(Context.getFunctionType(RetType, ArgType, EPI)); // Add the parameter to the operator. ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveAssignment, ClassLoc, ClassLoc, /*Id=*/0, ArgType, /*TInfo=*/0, - SC_None, SC_None, 0); MoveAssignment->setParams(FromParam); - // Note that we have added this copy-assignment operator. - ++ASTContext::NumImplicitMoveAssignmentOperatorsDeclared; + AddOverriddenMethods(ClassDecl, MoveAssignment); + + MoveAssignment->setTrivial( + ClassDecl->needsOverloadResolutionForMoveAssignment() + ? SpecialMemberIsTrivial(MoveAssignment, CXXMoveAssignment) + : ClassDecl->hasTrivialMoveAssignment()); // C++0x [class.copy]p9: // If the definition of a class X does not explicitly declare a move @@ -8337,11 +8930,13 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) { return 0; } + // Note that we have added this copy-assignment operator. + ++ASTContext::NumImplicitMoveAssignmentOperatorsDeclared; + if (Scope *S = getScopeForContext(ClassDecl)) PushOnScopeChains(MoveAssignment, S, false); ClassDecl->addDecl(MoveAssignment); - AddOverriddenMethods(ClassDecl, MoveAssignment); return MoveAssignment; } @@ -8431,7 +9026,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, VK_LValue, &BasePath); // Build the move. - StmtResult Move = BuildSingleCopyAssign(*this, Loc, BaseType, + StmtResult Move = buildSingleCopyAssign(*this, Loc, BaseType, To.get(), From, /*CopyingBaseSubobject=*/true, /*Copying=*/false); @@ -8446,11 +9041,6 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, Statements.push_back(Move.takeAs<Expr>()); } - // \brief Reference to the __builtin_memcpy function. - Expr *BuiltinMemCpyRef = 0; - // \brief Reference to the __builtin_objc_memmove_collectable function. - Expr *CollectableMemCpyRef = 0; - // Assign non-static members. for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), FieldEnd = ClassDecl->field_end(); @@ -8513,104 +9103,8 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, "Member reference with rvalue base must be rvalue except for reference " "members, which aren't allowed for move assignment."); - // If the field should be copied with __builtin_memcpy rather than via - // explicit assignments, do so. This optimization only applies for arrays - // of scalars and arrays of class type with trivial move-assignment - // operators. - if (FieldType->isArrayType() && !FieldType.isVolatileQualified() - && BaseType.hasTrivialAssignment(Context, /*Copying=*/false)) { - // Compute the size of the memory buffer to be copied. - QualType SizeType = Context.getSizeType(); - llvm::APInt Size(Context.getTypeSize(SizeType), - Context.getTypeSizeInChars(BaseType).getQuantity()); - for (const ConstantArrayType *Array - = Context.getAsConstantArrayType(FieldType); - Array; - Array = Context.getAsConstantArrayType(Array->getElementType())) { - llvm::APInt ArraySize - = Array->getSize().zextOrTrunc(Size.getBitWidth()); - Size *= ArraySize; - } - - // Take the address of the field references for "from" and "to". We - // directly construct UnaryOperators here because semantic analysis - // does not permit us to take the address of an xvalue. - From = new (Context) UnaryOperator(From.get(), UO_AddrOf, - Context.getPointerType(From.get()->getType()), - VK_RValue, OK_Ordinary, Loc); - To = new (Context) UnaryOperator(To.get(), UO_AddrOf, - Context.getPointerType(To.get()->getType()), - VK_RValue, OK_Ordinary, Loc); - - bool NeedsCollectableMemCpy = - (BaseType->isRecordType() && - BaseType->getAs<RecordType>()->getDecl()->hasObjectMember()); - - if (NeedsCollectableMemCpy) { - if (!CollectableMemCpyRef) { - // Create a reference to the __builtin_objc_memmove_collectable function. - LookupResult R(*this, - &Context.Idents.get("__builtin_objc_memmove_collectable"), - Loc, LookupOrdinaryName); - LookupName(R, TUScope, true); - - FunctionDecl *CollectableMemCpy = R.getAsSingle<FunctionDecl>(); - if (!CollectableMemCpy) { - // Something went horribly wrong earlier, and we will have - // complained about it. - Invalid = true; - continue; - } - - CollectableMemCpyRef = BuildDeclRefExpr(CollectableMemCpy, - Context.BuiltinFnTy, - VK_RValue, Loc, 0).take(); - assert(CollectableMemCpyRef && "Builtin reference cannot fail"); - } - } - // Create a reference to the __builtin_memcpy builtin function. - else if (!BuiltinMemCpyRef) { - LookupResult R(*this, &Context.Idents.get("__builtin_memcpy"), Loc, - LookupOrdinaryName); - LookupName(R, TUScope, true); - - FunctionDecl *BuiltinMemCpy = R.getAsSingle<FunctionDecl>(); - if (!BuiltinMemCpy) { - // Something went horribly wrong earlier, and we will have complained - // about it. - Invalid = true; - continue; - } - - BuiltinMemCpyRef = BuildDeclRefExpr(BuiltinMemCpy, - Context.BuiltinFnTy, - VK_RValue, Loc, 0).take(); - assert(BuiltinMemCpyRef && "Builtin reference cannot fail"); - } - - SmallVector<Expr*, 8> CallArgs; - CallArgs.push_back(To.takeAs<Expr>()); - CallArgs.push_back(From.takeAs<Expr>()); - CallArgs.push_back(IntegerLiteral::Create(Context, Size, SizeType, Loc)); - ExprResult Call = ExprError(); - if (NeedsCollectableMemCpy) - Call = ActOnCallExpr(/*Scope=*/0, - CollectableMemCpyRef, - Loc, CallArgs, - Loc); - else - Call = ActOnCallExpr(/*Scope=*/0, - BuiltinMemCpyRef, - Loc, CallArgs, - Loc); - - assert(!Call.isInvalid() && "Call to __builtin_memcpy cannot fail!"); - Statements.push_back(Call.takeAs<Expr>()); - continue; - } - // Build the move of this field. - StmtResult Move = BuildSingleCopyAssign(*this, Loc, FieldType, + StmtResult Move = buildSingleCopyAssign(*this, Loc, FieldType, To.get(), From.get(), /*CopyingBaseSubobject=*/false, /*Copying=*/false); @@ -8620,7 +9114,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, MoveAssignOperator->setInvalidDecl(); return; } - + // Success! Record the copy. Statements.push_back(Move.takeAs<Stmt>()); } @@ -8662,70 +9156,6 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, } } -/// Determine whether an implicit copy constructor for ClassDecl has a const -/// argument. -/// FIXME: It ought to be possible to store this on the record. -static bool isImplicitCopyCtorArgConst(Sema &S, CXXRecordDecl *ClassDecl) { - if (ClassDecl->isInvalidDecl()) - return true; - - // C++ [class.copy]p5: - // The implicitly-declared copy constructor for a class X will - // have the form - // - // X::X(const X&) - // - // if - // -- each direct or virtual base class B of X has a copy - // constructor whose first parameter is of type const B& or - // const volatile B&, and - for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), - BaseEnd = ClassDecl->bases_end(); - Base != BaseEnd; ++Base) { - // Virtual bases are handled below. - if (Base->isVirtual()) - continue; - - CXXRecordDecl *BaseClassDecl - = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); - // FIXME: This lookup is wrong. If the copy ctor for a member or base is - // ambiguous, we should still produce a constructor with a const-qualified - // parameter. - if (!S.LookupCopyingConstructor(BaseClassDecl, Qualifiers::Const)) - return false; - } - - for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(), - BaseEnd = ClassDecl->vbases_end(); - Base != BaseEnd; ++Base) { - CXXRecordDecl *BaseClassDecl - = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); - if (!S.LookupCopyingConstructor(BaseClassDecl, Qualifiers::Const)) - return false; - } - - // -- for all the nonstatic data members of X that are of a - // class type M (or array thereof), each such class type - // has a copy constructor whose first parameter is of type - // const M& or const volatile M&. - for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), - FieldEnd = ClassDecl->field_end(); - Field != FieldEnd; ++Field) { - QualType FieldType = S.Context.getBaseElementType(Field->getType()); - if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) { - if (!S.LookupCopyingConstructor(FieldClassDecl, Qualifiers::Const)) - return false; - } - } - - // Otherwise, the implicitly declared copy constructor will have - // the form - // - // X::X(X&) - - return true; -} - Sema::ImplicitExceptionSpecification Sema::ComputeDefaultedCopyCtorExceptionSpec(CXXMethodDecl *MD) { CXXRecordDecl *ClassDecl = MD->getParent(); @@ -8786,10 +9216,15 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( // C++ [class.copy]p4: // If the class definition does not explicitly declare a copy // constructor, one is declared implicitly. + assert(ClassDecl->needsImplicitCopyConstructor()); + + DeclaringSpecialMember DSM(*this, ClassDecl, CXXCopyConstructor); + if (DSM.isAlreadyBeingDeclared()) + return 0; QualType ClassType = Context.getTypeDeclType(ClassDecl); QualType ArgType = ClassType; - bool Const = isImplicitCopyCtorArgConst(*this, ClassDecl); + bool Const = ClassDecl->implicitCopyConstructorHasConstParam(); if (Const) ArgType = ArgType.withConst(); ArgType = Context.getLValueReferenceType(ArgType); @@ -8812,30 +9247,26 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( Constexpr); CopyConstructor->setAccess(AS_public); CopyConstructor->setDefaulted(); - CopyConstructor->setTrivial(ClassDecl->hasTrivialCopyConstructor()); // Build an exception specification pointing back at this member. FunctionProtoType::ExtProtoInfo EPI; EPI.ExceptionSpecType = EST_Unevaluated; EPI.ExceptionSpecDecl = CopyConstructor; CopyConstructor->setType( - Context.getFunctionType(Context.VoidTy, &ArgType, 1, EPI)); + Context.getFunctionType(Context.VoidTy, ArgType, EPI)); - // Note that we have declared this constructor. - ++ASTContext::NumImplicitCopyConstructorsDeclared; - // Add the parameter to the constructor. ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyConstructor, ClassLoc, ClassLoc, /*IdentifierInfo=*/0, ArgType, /*TInfo=*/0, - SC_None, SC_None, 0); CopyConstructor->setParams(FromParam); - if (Scope *S = getScopeForContext(ClassDecl)) - PushOnScopeChains(CopyConstructor, S, false); - ClassDecl->addDecl(CopyConstructor); + CopyConstructor->setTrivial( + ClassDecl->needsOverloadResolutionForCopyConstructor() + ? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor) + : ClassDecl->hasTrivialCopyConstructor()); // C++11 [class.copy]p8: // ... If the class definition does not explicitly declare a copy @@ -8843,7 +9274,14 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( // user-declared move assignment operator, a copy constructor is implicitly // declared as defaulted. if (ShouldDeleteSpecialMember(CopyConstructor, CXXCopyConstructor)) - CopyConstructor->setDeletedAsWritten(); + SetDeclDeleted(CopyConstructor, ClassLoc); + + // Note that we have declared this constructor. + ++ASTContext::NumImplicitCopyConstructorsDeclared; + + if (Scope *S = getScopeForContext(ClassDecl)) + PushOnScopeChains(CopyConstructor, S, false); + ClassDecl->addDecl(CopyConstructor); return CopyConstructor; } @@ -8862,7 +9300,7 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation, SynthesizedFunctionScope Scope(*this, CopyConstructor); DiagnosticErrorTrap Trap(Diags); - if (SetCtorInitializers(CopyConstructor, 0, 0, /*AnyErrors=*/false) || + if (SetCtorInitializers(CopyConstructor, /*AnyErrors=*/false) || Trap.hasErrorOccurred()) { Diag(CurrentLocation, diag::note_member_synthesized_at) << CXXCopyConstructor << Context.getTagDeclType(ClassDecl); @@ -8957,6 +9395,10 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor( // - [first 4 bullets] assert(ClassDecl->needsImplicitMoveConstructor()); + DeclaringSpecialMember DSM(*this, ClassDecl, CXXMoveConstructor); + if (DSM.isAlreadyBeingDeclared()) + return 0; + // [Checked after we build the declaration] // - the move assignment operator would not be implicitly defined as // deleted, @@ -8991,24 +9433,27 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor( Constexpr); MoveConstructor->setAccess(AS_public); MoveConstructor->setDefaulted(); - MoveConstructor->setTrivial(ClassDecl->hasTrivialMoveConstructor()); // Build an exception specification pointing back at this member. FunctionProtoType::ExtProtoInfo EPI; EPI.ExceptionSpecType = EST_Unevaluated; EPI.ExceptionSpecDecl = MoveConstructor; MoveConstructor->setType( - Context.getFunctionType(Context.VoidTy, &ArgType, 1, EPI)); + Context.getFunctionType(Context.VoidTy, ArgType, EPI)); // Add the parameter to the constructor. ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveConstructor, ClassLoc, ClassLoc, /*IdentifierInfo=*/0, ArgType, /*TInfo=*/0, - SC_None, SC_None, 0); MoveConstructor->setParams(FromParam); + MoveConstructor->setTrivial( + ClassDecl->needsOverloadResolutionForMoveConstructor() + ? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor) + : ClassDecl->hasTrivialMoveConstructor()); + // C++0x [class.copy]p9: // If the definition of a class X does not explicitly declare a move // constructor, one will be implicitly declared as defaulted if and only if: @@ -9045,7 +9490,7 @@ void Sema::DefineImplicitMoveConstructor(SourceLocation CurrentLocation, SynthesizedFunctionScope Scope(*this, MoveConstructor); DiagnosticErrorTrap Trap(Diags); - if (SetCtorInitializers(MoveConstructor, 0, 0, /*AnyErrors=*/false) || + if (SetCtorInitializers(MoveConstructor, /*AnyErrors=*/false) || Trap.hasErrorOccurred()) { Diag(CurrentLocation, diag::note_member_synthesized_at) << CXXMoveConstructor << Context.getTagDeclType(ClassDecl); @@ -9077,8 +9522,8 @@ bool Sema::isImplicitlyDeleted(FunctionDecl *FD) { static void markLambdaCallOperatorUsed(Sema &S, CXXRecordDecl *Lambda) { CXXMethodDecl *CallOperator = cast<CXXMethodDecl>( - *Lambda->lookup( - S.Context.DeclarationNames.getCXXOperatorName(OO_Call)).first); + Lambda->lookup( + S.Context.DeclarationNames.getCXXOperatorName(OO_Call)).front()); CallOperator->setReferenced(); CallOperator->setUsed(); } @@ -9100,12 +9545,12 @@ void Sema::DefineImplicitLambdaToFunctionPointerConversion( // Return the address of the __invoke function. DeclarationName InvokeName = &Context.Idents.get("__invoke"); CXXMethodDecl *Invoke - = cast<CXXMethodDecl>(*Lambda->lookup(InvokeName).first); + = cast<CXXMethodDecl>(Lambda->lookup(InvokeName).front()); Expr *FunctionRef = BuildDeclRefExpr(Invoke, Invoke->getType(), VK_LValue, Conv->getLocation()).take(); assert(FunctionRef && "Can't refer to __invoke function?"); Stmt *Return = ActOnReturnStmt(Conv->getLocation(), FunctionRef).take(); - Conv->setBody(new (Context) CompoundStmt(Context, &Return, 1, + Conv->setBody(new (Context) CompoundStmt(Context, Return, Conv->getLocation(), Conv->getLocation())); @@ -9164,7 +9609,7 @@ void Sema::DefineImplicitLambdaToBlockPointerConversion( // Set the body of the conversion function. Stmt *ReturnS = Return.take(); - Conv->setBody(new (Context) CompoundStmt(Context, &ReturnS, 1, + Conv->setBody(new (Context) CompoundStmt(Context, ReturnS, Conv->getLocation(), Conv->getLocation())); @@ -9198,6 +9643,7 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, CXXConstructorDecl *Constructor, MultiExprArg ExprArgs, bool HadMultipleCandidates, + bool IsListInitialization, bool RequiresZeroInit, unsigned ConstructKind, SourceRange ParenRange) { @@ -9221,7 +9667,8 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, return BuildCXXConstructExpr(ConstructLoc, DeclInitType, Constructor, Elidable, ExprArgs, HadMultipleCandidates, - RequiresZeroInit, ConstructKind, ParenRange); + IsListInitialization, RequiresZeroInit, + ConstructKind, ParenRange); } /// BuildCXXConstructExpr - Creates a complete call to a constructor, @@ -9231,39 +9678,19 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, CXXConstructorDecl *Constructor, bool Elidable, MultiExprArg ExprArgs, bool HadMultipleCandidates, + bool IsListInitialization, bool RequiresZeroInit, unsigned ConstructKind, SourceRange ParenRange) { MarkFunctionReferenced(ConstructLoc, Constructor); return Owned(CXXConstructExpr::Create(Context, DeclInitType, ConstructLoc, Constructor, Elidable, ExprArgs, - HadMultipleCandidates, /*FIXME*/false, - RequiresZeroInit, + HadMultipleCandidates, + IsListInitialization, RequiresZeroInit, static_cast<CXXConstructExpr::ConstructionKind>(ConstructKind), ParenRange)); } -bool Sema::InitializeVarWithConstructor(VarDecl *VD, - CXXConstructorDecl *Constructor, - MultiExprArg Exprs, - bool HadMultipleCandidates) { - // FIXME: Provide the correct paren SourceRange when available. - ExprResult TempResult = - BuildCXXConstructExpr(VD->getLocation(), VD->getType(), Constructor, - Exprs, HadMultipleCandidates, false, - CXXConstructExpr::CK_Complete, SourceRange()); - if (TempResult.isInvalid()) - return true; - - Expr *Temp = TempResult.takeAs<Expr>(); - CheckImplicitConversions(Temp, VD->getLocation()); - MarkFunctionReferenced(VD->getLocation(), Constructor); - Temp = MaybeCreateExprWithCleanups(Temp); - VD->setInit(Temp); - - return false; -} - void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) { if (VD->isInvalidDecl()) return; @@ -9301,7 +9728,8 @@ Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor, MultiExprArg ArgsPtr, SourceLocation Loc, SmallVectorImpl<Expr*> &ConvertedArgs, - bool AllowExplicit) { + bool AllowExplicit, + bool IsListInitialization) { // FIXME: This duplicates a lot of code from Sema::ConvertArgumentsForCall. unsigned NumArgs = ArgsPtr.size(); Expr **Args = ArgsPtr.data(); @@ -9322,12 +9750,15 @@ Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor, SmallVector<Expr *, 8> AllArgs; bool Invalid = GatherArgumentsForCall(Loc, Constructor, Proto, 0, Args, NumArgs, AllArgs, - CallType, AllowExplicit); + CallType, AllowExplicit, + IsListInitialization); ConvertedArgs.append(AllArgs.begin(), AllArgs.end()); DiagnoseSentinelCalls(Constructor, Loc, AllArgs.data(), AllArgs.size()); - CheckConstructorCall(Constructor, AllArgs.data(), AllArgs.size(), + CheckConstructorCall(Constructor, + llvm::makeArrayRef<const Expr *>(AllArgs.data(), + AllArgs.size()), Proto, Loc); return Invalid; @@ -9766,6 +10197,19 @@ Decl *Sema::ActOnFinishLinkageSpecification(Scope *S, return LinkageSpec; } +Decl *Sema::ActOnEmptyDeclaration(Scope *S, + AttributeList *AttrList, + SourceLocation SemiLoc) { + Decl *ED = EmptyDecl::Create(Context, CurContext, SemiLoc); + // Attribute declarations appertain to empty declaration so we handle + // them here. + if (AttrList) + ProcessDeclAttributeList(S, ED, AttrList); + + CurContext->addDecl(ED); + return ED; +} + /// \brief Perform semantic analysis for the variable declaration that /// occurs within a C++ catch clause, returning the newly-created /// variable. @@ -9833,7 +10277,7 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, } VarDecl *ExDecl = VarDecl::Create(Context, CurContext, StartLoc, Loc, Name, - ExDeclType, TInfo, SC_None, SC_None); + ExDeclType, TInfo, SC_None); ExDecl->setExceptionVariable(true); // In ARC, infer 'retaining' for variables of retainable type. @@ -9842,6 +10286,9 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, if (!Invalid && !ExDeclType->isDependentType()) { if (const RecordType *recordType = ExDeclType->getAs<RecordType>()) { + // Insulate this from anything else we might currently be parsing. + EnterExpressionEvaluationContext scope(*this, PotentiallyEvaluated); + // C++ [except.handle]p16: // The object declared in an exception-declaration or, if the // exception-declaration does not specify a name, a temporary (12.2) is @@ -9893,8 +10340,8 @@ Decl *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) { bool Invalid = D.isInvalidType(); // Check for unexpanded parameter packs. - if (TInfo && DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo, - UPPC_ExceptionType)) { + if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo, + UPPC_ExceptionType)) { TInfo = Context.getTrivialTypeSourceInfo(Context.IntTy, D.getIdentifierLoc()); Invalid = true; @@ -9970,7 +10417,7 @@ Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc, Failed = true; if (!Failed && !Cond) { - llvm::SmallString<256> MsgBuffer; + SmallString<256> MsgBuffer; llvm::raw_svector_ostream Msg(MsgBuffer); AssertMessage->printPretty(Msg, 0, getPrintingPolicy()); Diag(StaticAssertLoc, diag::err_static_assert_failed) @@ -10007,47 +10454,49 @@ FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation LocStart, // Do not complain about the form of friend template types during // template instantiation; we will already have complained when the // template was declared. - } else if (!T->isElaboratedTypeSpecifier()) { - // If we evaluated the type to a record type, suggest putting - // a tag in front. - if (const RecordType *RT = T->getAs<RecordType>()) { - RecordDecl *RD = RT->getDecl(); + } else { + if (!T->isElaboratedTypeSpecifier()) { + // If we evaluated the type to a record type, suggest putting + // a tag in front. + if (const RecordType *RT = T->getAs<RecordType>()) { + RecordDecl *RD = RT->getDecl(); - std::string InsertionText = std::string(" ") + RD->getKindName(); + std::string InsertionText = std::string(" ") + RD->getKindName(); - Diag(TypeRange.getBegin(), - getLangOpts().CPlusPlus0x ? - diag::warn_cxx98_compat_unelaborated_friend_type : - diag::ext_unelaborated_friend_type) - << (unsigned) RD->getTagKind() - << T - << FixItHint::CreateInsertion(PP.getLocForEndOfToken(FriendLoc), - InsertionText); - } else { + Diag(TypeRange.getBegin(), + getLangOpts().CPlusPlus11 ? + diag::warn_cxx98_compat_unelaborated_friend_type : + diag::ext_unelaborated_friend_type) + << (unsigned) RD->getTagKind() + << T + << FixItHint::CreateInsertion(PP.getLocForEndOfToken(FriendLoc), + InsertionText); + } else { + Diag(FriendLoc, + getLangOpts().CPlusPlus11 ? + diag::warn_cxx98_compat_nonclass_type_friend : + diag::ext_nonclass_type_friend) + << T + << TypeRange; + } + } else if (T->getAs<EnumType>()) { Diag(FriendLoc, - getLangOpts().CPlusPlus0x ? - diag::warn_cxx98_compat_nonclass_type_friend : - diag::ext_nonclass_type_friend) + getLangOpts().CPlusPlus11 ? + diag::warn_cxx98_compat_enum_friend : + diag::ext_enum_friend) << T << TypeRange; } - } else if (T->getAs<EnumType>()) { - Diag(FriendLoc, - getLangOpts().CPlusPlus0x ? - diag::warn_cxx98_compat_enum_friend : - diag::ext_enum_friend) - << T - << TypeRange; - } - // C++11 [class.friend]p3: - // A friend declaration that does not declare a function shall have one - // of the following forms: - // friend elaborated-type-specifier ; - // friend simple-type-specifier ; - // friend typename-specifier ; - if (getLangOpts().CPlusPlus0x && LocStart != FriendLoc) - Diag(FriendLoc, diag::err_friend_not_first_in_declaration) << T; + // C++11 [class.friend]p3: + // A friend declaration that does not declare a function shall have one + // of the following forms: + // friend elaborated-type-specifier ; + // friend simple-type-specifier ; + // friend typename-specifier ; + if (getLangOpts().CPlusPlus11 && LocStart != FriendLoc) + Diag(FriendLoc, diag::err_friend_not_first_in_declaration) << T; + } // If the type specifier in a friend declaration designates a (possibly // cv-qualified) class type, that class is declared as a friend; otherwise, @@ -10060,7 +10509,8 @@ FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation LocStart, Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, unsigned TagSpec, SourceLocation TagLoc, CXXScopeSpec &SS, - IdentifierInfo *Name, SourceLocation NameLoc, + IdentifierInfo *Name, + SourceLocation NameLoc, AttributeList *Attr, MultiTemplateParamsArg TempParamLists) { TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec); @@ -10132,19 +10582,20 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T); if (isa<DependentNameType>(T)) { - DependentNameTypeLoc TL = cast<DependentNameTypeLoc>(TSI->getTypeLoc()); + DependentNameTypeLoc TL = + TSI->getTypeLoc().castAs<DependentNameTypeLoc>(); TL.setElaboratedKeywordLoc(TagLoc); TL.setQualifierLoc(QualifierLoc); TL.setNameLoc(NameLoc); } else { - ElaboratedTypeLoc TL = cast<ElaboratedTypeLoc>(TSI->getTypeLoc()); + ElaboratedTypeLoc TL = TSI->getTypeLoc().castAs<ElaboratedTypeLoc>(); TL.setElaboratedKeywordLoc(TagLoc); TL.setQualifierLoc(QualifierLoc); - cast<TypeSpecTypeLoc>(TL.getNamedTypeLoc()).setNameLoc(NameLoc); + TL.getNamedTypeLoc().castAs<TypeSpecTypeLoc>().setNameLoc(NameLoc); } FriendDecl *Friend = FriendDecl::Create(Context, CurContext, NameLoc, - TSI, FriendLoc); + TSI, FriendLoc, TempParamLists); Friend->setAccess(AS_public); CurContext->addDecl(Friend); return Friend; @@ -10160,13 +10611,13 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, ElaboratedTypeKeyword ETK = TypeWithKeyword::getKeywordForTagTypeKind(Kind); QualType T = Context.getDependentNameType(ETK, SS.getScopeRep(), Name); TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T); - DependentNameTypeLoc TL = cast<DependentNameTypeLoc>(TSI->getTypeLoc()); + DependentNameTypeLoc TL = TSI->getTypeLoc().castAs<DependentNameTypeLoc>(); TL.setElaboratedKeywordLoc(TagLoc); TL.setQualifierLoc(SS.getWithLocInContext(Context)); TL.setNameLoc(NameLoc); FriendDecl *Friend = FriendDecl::Create(Context, CurContext, NameLoc, - TSI, FriendLoc); + TSI, FriendLoc, TempParamLists); Friend->setAccess(AS_public); Friend->setUnsupportedFriend(true); CurContext->addDecl(Friend); @@ -10260,8 +10711,8 @@ Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, return D; } -Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, - MultiTemplateParamsArg TemplateParams) { +NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, + MultiTemplateParamsArg TemplateParams) { const DeclSpec &DS = D.getDeclSpec(); assert(DS.isFriendSpecified()); @@ -10372,17 +10823,6 @@ Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, DC = DC->getParent(); } - // C++ [class.friend]p1: A friend of a class is a function or - // class that is not a member of the class . . . - // C++11 changes this for both friend types and functions. - // Most C++ 98 compilers do seem to give an error here, so - // we do, too. - if (!Previous.empty() && DC->Equals(CurContext)) - Diag(DS.getFriendSpecLoc(), - getLangOpts().CPlusPlus0x ? - diag::warn_cxx98_compat_friend_is_member : - diag::err_friend_is_member); - DCScope = getScopeForDeclContext(S, DC); // C++ [class.friend]p6: @@ -10427,7 +10867,7 @@ Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, // class that is not a member of the class . . . if (DC->Equals(CurContext)) Diag(DS.getFriendSpecLoc(), - getLangOpts().CPlusPlus0x ? + getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_friend_is_member : diag::err_friend_is_member); @@ -10534,11 +10974,12 @@ Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) { AdjustDeclIfTemplate(Dcl); - FunctionDecl *Fn = dyn_cast<FunctionDecl>(Dcl); + FunctionDecl *Fn = dyn_cast_or_null<FunctionDecl>(Dcl); if (!Fn) { Diag(DelLoc, diag::err_deleted_non_function); return; } + if (const FunctionDecl *Prev = Fn->getPreviousDecl()) { // Don't consider the implicit declaration we generate for explicit // specializations. FIXME: Do not generate these implicit declarations. @@ -10549,41 +10990,34 @@ void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) { } // If the declaration wasn't the first, we delete the function anyway for // recovery. + Fn = Fn->getCanonicalDecl(); } - Fn->setDeletedAsWritten(); - CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Dcl); - if (!MD) + if (Fn->isDeleted()) return; - // A deleted special member function is trivial if the corresponding - // implicitly-declared function would have been. - switch (getSpecialMember(MD)) { - case CXXInvalid: - break; - case CXXDefaultConstructor: - MD->setTrivial(MD->getParent()->hasTrivialDefaultConstructor()); - break; - case CXXCopyConstructor: - MD->setTrivial(MD->getParent()->hasTrivialCopyConstructor()); - break; - case CXXMoveConstructor: - MD->setTrivial(MD->getParent()->hasTrivialMoveConstructor()); - break; - case CXXCopyAssignment: - MD->setTrivial(MD->getParent()->hasTrivialCopyAssignment()); - break; - case CXXMoveAssignment: - MD->setTrivial(MD->getParent()->hasTrivialMoveAssignment()); - break; - case CXXDestructor: - MD->setTrivial(MD->getParent()->hasTrivialDestructor()); - break; + // See if we're deleting a function which is already known to override a + // non-deleted virtual function. + if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Fn)) { + bool IssuedDiagnostic = false; + for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(), + E = MD->end_overridden_methods(); + I != E; ++I) { + if (!(*MD->begin_overridden_methods())->isDeleted()) { + if (!IssuedDiagnostic) { + Diag(DelLoc, diag::err_deleted_override) << MD->getDeclName(); + IssuedDiagnostic = true; + } + Diag((*I)->getLocation(), diag::note_overridden_virtual_function); + } + } } + + Fn->setDeletedAsWritten(); } void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) { - CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Dcl); + CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(Dcl); if (MD) { if (MD->getParent()->isDependentType()) { @@ -10609,11 +11043,19 @@ void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) { // on it. Pattern->isDefined(Primary); + // If the method was defaulted on its first declaration, we will have + // already performed the checking in CheckCompletedCXXClass. Such a + // declaration doesn't trigger an implicit definition. if (Primary == Primary->getCanonicalDecl()) return; CheckExplicitlyDefaultedSpecialMember(MD); + // The exception specification is needed because we are defining the + // function. + ResolveExceptionSpec(DefaultLoc, + MD->getType()->castAs<FunctionProtoType>()); + switch (Member) { case CXXDefaultConstructor: { CXXConstructorDecl *CD = cast<CXXConstructorDecl>(MD); @@ -10683,6 +11125,40 @@ void Sema::DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock) { } } +bool Sema::CheckOverridingFunctionAttributes(const CXXMethodDecl *New, + const CXXMethodDecl *Old) { + const FunctionType *NewFT = New->getType()->getAs<FunctionType>(); + const FunctionType *OldFT = Old->getType()->getAs<FunctionType>(); + + CallingConv NewCC = NewFT->getCallConv(), OldCC = OldFT->getCallConv(); + + // If the calling conventions match, everything is fine + if (NewCC == OldCC) + return false; + + // If either of the calling conventions are set to "default", we need to pick + // something more sensible based on the target. This supports code where the + // one method explicitly sets thiscall, and another has no explicit calling + // convention. + CallingConv Default = + Context.getTargetInfo().getDefaultCallingConv(TargetInfo::CCMT_Member); + if (NewCC == CC_Default) + NewCC = Default; + if (OldCC == CC_Default) + OldCC = Default; + + // If the calling conventions still don't match, then report the error + if (NewCC != OldCC) { + Diag(New->getLocation(), + diag::err_conflicting_overriding_cc_attributes) + << New->getDeclName() << New->getType() << Old->getType(); + Diag(Old->getLocation(), diag::note_overridden_virtual_function); + return true; + } + + return false; +} + bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, const CXXMethodDecl *Old) { QualType NewTy = New->getType()->getAs<FunctionType>()->getResultType(); @@ -10949,7 +11425,7 @@ bool Sema::DefineUsedVTables() { // If this class has a key function, but that key function is // defined in another translation unit, we don't need to emit the // vtable even though we're using it. - const CXXMethodDecl *KeyFunction = Context.getKeyFunction(Class); + const CXXMethodDecl *KeyFunction = Context.getCurrentKeyFunction(Class); if (KeyFunction && !KeyFunction->hasBody()) { switch (KeyFunction->getTemplateSpecializationKind()) { case TSK_Undeclared: @@ -11006,7 +11482,7 @@ bool Sema::DefineUsedVTables() { Consumer.HandleVTable(Class, VTablesUsed[Canonical]); // Optionally warn if we're emitting a weak vtable. - if (Class->getLinkage() == ExternalLinkage && + if (Class->hasExternalLinkage() && Class->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) { const FunctionDecl *KeyFunctionDef = 0; if (!KeyFunction || @@ -11228,7 +11704,7 @@ bool Sema::checkThisInStaticMemberFunctionType(CXXMethodDecl *Method) { return false; TypeLoc TL = TSInfo->getTypeLoc(); - FunctionProtoTypeLoc *ProtoTL = dyn_cast<FunctionProtoTypeLoc>(&TL); + FunctionProtoTypeLoc ProtoTL = TL.getAs<FunctionProtoTypeLoc>(); if (!ProtoTL) return false; @@ -11239,12 +11715,12 @@ bool Sema::checkThisInStaticMemberFunctionType(CXXMethodDecl *Method) { // within a static member function as they are within a non-static member // function). [ Note: this is because declaration matching does not occur // until the complete declarator is known. - end note ] - const FunctionProtoType *Proto = ProtoTL->getTypePtr(); + const FunctionProtoType *Proto = ProtoTL.getTypePtr(); FindCXXThisExpr Finder(*this); // If the return type came after the cv-qualifier-seq, check it now. if (Proto->hasTrailingReturn() && - !Finder.TraverseTypeLoc(ProtoTL->getResultLoc())) + !Finder.TraverseTypeLoc(ProtoTL.getResultLoc())) return true; // Check the exception specification. @@ -11260,11 +11736,11 @@ bool Sema::checkThisInStaticMemberFunctionExceptionSpec(CXXMethodDecl *Method) { return false; TypeLoc TL = TSInfo->getTypeLoc(); - FunctionProtoTypeLoc *ProtoTL = dyn_cast<FunctionProtoTypeLoc>(&TL); + FunctionProtoTypeLoc ProtoTL = TL.getAs<FunctionProtoTypeLoc>(); if (!ProtoTL) return false; - const FunctionProtoType *Proto = ProtoTL->getTypePtr(); + const FunctionProtoType *Proto = ProtoTL.getTypePtr(); FindCXXThisExpr Finder(*this); switch (Proto->getExceptionSpecType()) { @@ -11354,7 +11830,7 @@ Sema::checkExceptionSpecification(ExceptionSpecificationType EST, ArrayRef<ParsedType> DynamicExceptions, ArrayRef<SourceRange> DynamicExceptionRanges, Expr *NoexceptExpr, - llvm::SmallVectorImpl<QualType> &Exceptions, + SmallVectorImpl<QualType> &Exceptions, FunctionProtoType::ExtProtoInfo &EPI) { Exceptions.clear(); EPI.ExceptionSpecType = EST; |