diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp | 3141 |
1 files changed, 1731 insertions, 1410 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp index a39584a..847f03c 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp @@ -16,6 +16,7 @@ #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" @@ -31,7 +32,7 @@ #include "clang/Sema/ParsedTemplate.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Lex/Preprocessor.h" -#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/STLExtras.h" #include <map> #include <set> @@ -60,6 +61,7 @@ namespace { bool VisitExpr(Expr *Node); bool VisitDeclRefExpr(DeclRefExpr *DRE); bool VisitCXXThisExpr(CXXThisExpr *ThisE); + bool VisitLambdaExpr(LambdaExpr *Lambda); }; /// VisitExpr - Visit all of the children of this expression. @@ -84,7 +86,7 @@ namespace { // evaluated. Parameters of a function declared before a default // argument expression are in scope and can hide namespace and // class member names. - return S->Diag(DRE->getSourceRange().getBegin(), + return S->Diag(DRE->getLocStart(), diag::err_param_default_argument_references_param) << Param->getDeclName() << DefaultArg->getSourceRange(); } else if (VarDecl *VDecl = dyn_cast<VarDecl>(Decl)) { @@ -92,7 +94,7 @@ namespace { // Local variables shall not be used in default argument // expressions. if (VDecl->isLocalVarDecl()) - return S->Diag(DRE->getSourceRange().getBegin(), + return S->Diag(DRE->getLocStart(), diag::err_param_default_argument_references_local) << VDecl->getDeclName() << DefaultArg->getSourceRange(); } @@ -105,10 +107,21 @@ namespace { // C++ [dcl.fct.default]p8: // The keyword this shall not be used in a default argument of a // member function. - return S->Diag(ThisE->getSourceRange().getBegin(), + return S->Diag(ThisE->getLocStart(), diag::err_param_default_argument_references_this) << ThisE->getSourceRange(); } + + bool CheckDefaultArgumentVisitor::VisitLambdaExpr(LambdaExpr *Lambda) { + // C++11 [expr.lambda.prim]p13: + // A lambda-expression appearing in a default argument shall not + // implicitly or explicitly capture any entity. + if (Lambda->capture_begin() == Lambda->capture_end()) + return false; + + return S->Diag(Lambda->getLocStart(), + diag::err_lambda_capture_default_arg); + } } void Sema::ImplicitExceptionSpecification::CalledDecl(CXXMethodDecl *Method) { @@ -267,7 +280,7 @@ Sema::ActOnParamDefaultArgument(Decl *param, SourceLocation EqualLoc, UnparsedDefaultArgLocs.erase(Param); // Default arguments are only permitted in C++ - if (!getLangOptions().CPlusPlus) { + if (!getLangOpts().CPlusPlus) { Diag(EqualLoc, diag::err_param_default_argument) << DefaultArg->getSourceRange(); Param->setInvalidDecl(); @@ -359,7 +372,8 @@ void Sema::CheckExtraCXXDefaultArguments(Declarator &D) { // function, once we already know that they have the same // type. Subroutine of MergeFunctionDecl. Returns true if there was an // error, false otherwise. -bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) { +bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, + Scope *S) { bool Invalid = false; // C++ [dcl.fct.default]p4: @@ -384,7 +398,16 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) { ParmVarDecl *OldParam = Old->getParamDecl(p); ParmVarDecl *NewParam = New->getParamDecl(p); - if (OldParam->hasDefaultArg() && NewParam->hasDefaultArg()) { + bool OldParamHasDfl = OldParam->hasDefaultArg(); + bool NewParamHasDfl = NewParam->hasDefaultArg(); + + NamedDecl *ND = Old; + if (S && !isDeclInScope(ND, New->getDeclContext(), S)) + // Ignore default parameters of old decl if they are not in + // the same scope. + OldParamHasDfl = false; + + if (OldParamHasDfl && NewParamHasDfl) { unsigned DiagDefaultParamID = diag::err_param_default_argument_redefinition; @@ -392,7 +415,7 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) { // MSVC accepts that default parameters be redefined for member functions // of template class. The new default parameter's value is ignored. Invalid = true; - if (getLangOptions().MicrosoftExt) { + if (getLangOpts().MicrosoftExt) { CXXMethodDecl* MD = dyn_cast<CXXMethodDecl>(New); if (MD && MD->getParent()->getDescribedClassTemplate()) { // Merge the old default argument into the new parameter. @@ -420,8 +443,8 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) { // Look for the function declaration where the default argument was // actually written, which may be a declaration prior to Old. - for (FunctionDecl *Older = Old->getPreviousDeclaration(); - Older; Older = Older->getPreviousDeclaration()) { + for (FunctionDecl *Older = Old->getPreviousDecl(); + Older; Older = Older->getPreviousDecl()) { if (!Older->getParamDecl(p)->hasDefaultArg()) break; @@ -430,7 +453,7 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) { Diag(OldParam->getLocation(), diag::note_previous_definition) << OldParam->getDefaultArgRange(); - } else if (OldParam->hasDefaultArg()) { + } else if (OldParamHasDfl) { // Merge the old default argument into the new parameter. // It's important to use getInit() here; getDefaultArg() // strips off any top-level ExprWithCleanups. @@ -440,7 +463,7 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) { OldParam->getUninstantiatedDefaultArg()); else NewParam->setDefaultArg(OldParam->getInit()); - } else if (NewParam->hasDefaultArg()) { + } else if (NewParamHasDfl) { if (New->getDescribedFunctionTemplate()) { // Paragraph 4, quoted above, only applies to non-template functions. Diag(NewParam->getLocation(), @@ -502,13 +525,9 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) { } } - // C++0x [dcl.constexpr]p1: If any declaration of a function or function + // 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. [Note: An explicit specialization can - // differ from the template declaration with respect to the constexpr - // specifier. -- end note] - // - // FIXME: Don't reject changes in constexpr in explicit specializations. + // contain the constexpr specifier. if (New->isConstexpr() != Old->isConstexpr()) { Diag(New->getLocation(), diag::err_constexpr_redecl_mismatch) << New << New->isConstexpr(); @@ -529,7 +548,7 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) { /// validates compatibility and merges the specs if necessary. void Sema::MergeVarDeclExceptionSpecs(VarDecl *New, VarDecl *Old) { // Shortcut if exceptions are disabled. - if (!getLangOptions().CXXExceptions) + if (!getLangOpts().CXXExceptions) return; assert(Context.hasSameType(New->getType(), Old->getType()) && @@ -571,11 +590,25 @@ void Sema::CheckCXXDefaultArguments(FunctionDecl *FD) { unsigned NumParams = FD->getNumParams(); unsigned p; + bool IsLambda = FD->getOverloadedOperator() == OO_Call && + isa<CXXMethodDecl>(FD) && + cast<CXXMethodDecl>(FD)->getParent()->isLambda(); + // Find first parameter with a default argument for (p = 0; p < NumParams; ++p) { ParmVarDecl *Param = FD->getParamDecl(p); - if (Param->hasDefaultArg()) + if (Param->hasDefaultArg()) { + // C++11 [expr.prim.lambda]p5: + // [...] Default arguments (8.3.6) shall not be specified in the + // parameter-declaration-clause of a lambda-declarator. + // + // FIXME: Core issue 974 strikes this sentence, we only provide an + // extension warning. + if (IsLambda) + Diag(Param->getLocation(), diag::ext_lambda_default_arguments) + << Param->getDefaultArgRange(); break; + } } // C++ [dcl.fct.default]p4: @@ -618,9 +651,9 @@ void Sema::CheckCXXDefaultArguments(FunctionDecl *FD) { // CheckConstexprParameterTypes - Check whether a function's parameter types // are all literal types. If so, return true. If not, produce a suitable -// diagnostic depending on @p CCK and return false. -static bool CheckConstexprParameterTypes(Sema &SemaRef, const FunctionDecl *FD, - Sema::CheckConstexprKind CCK) { +// diagnostic and return false. +static bool CheckConstexprParameterTypes(Sema &SemaRef, + const FunctionDecl *FD) { unsigned ArgIndex = 0; const FunctionProtoType *FT = FD->getType()->getAs<FunctionProtoType>(); for (FunctionProtoType::arg_type_iterator i = FT->arg_type_begin(), @@ -628,107 +661,73 @@ static bool CheckConstexprParameterTypes(Sema &SemaRef, const FunctionDecl *FD, const ParmVarDecl *PD = FD->getParamDecl(ArgIndex); SourceLocation ParamLoc = PD->getLocation(); if (!(*i)->isDependentType() && - SemaRef.RequireLiteralType(ParamLoc, *i, CCK == Sema::CCK_Declaration ? + SemaRef.RequireLiteralType(ParamLoc, *i, SemaRef.PDiag(diag::err_constexpr_non_literal_param) << ArgIndex+1 << PD->getSourceRange() - << isa<CXXConstructorDecl>(FD) : - SemaRef.PDiag(), - /*AllowIncompleteType*/ true)) { - if (CCK == Sema::CCK_NoteNonConstexprInstantiation) - SemaRef.Diag(ParamLoc, diag::note_constexpr_tmpl_non_literal_param) - << ArgIndex+1 << PD->getSourceRange() - << isa<CXXConstructorDecl>(FD) << *i; + << isa<CXXConstructorDecl>(FD))) return false; - } } return true; } // CheckConstexprFunctionDecl - Check whether a function declaration satisfies -// the requirements of a constexpr function declaration or a constexpr -// constructor declaration. Return true if it does, false if not. -// -// This implements C++0x [dcl.constexpr]p3,4, as amended by N3308. +// the requirements of a constexpr function definition or a constexpr +// constructor definition. If so, return true. If not, produce appropriate +// diagnostics and return false. // -// \param CCK Specifies whether to produce diagnostics if the function does not -// satisfy the requirements. -bool Sema::CheckConstexprFunctionDecl(const FunctionDecl *NewFD, - CheckConstexprKind CCK) { - assert((CCK != CCK_NoteNonConstexprInstantiation || - (NewFD->getTemplateInstantiationPattern() && - NewFD->getTemplateInstantiationPattern()->isConstexpr())) && - "only constexpr templates can be instantiated non-constexpr"); - - if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(NewFD)) { - // C++0x [dcl.constexpr]p4: - // In the definition of a constexpr constructor, each of the parameter - // types shall be a literal type. - if (!CheckConstexprParameterTypes(*this, NewFD, CCK)) - return false; - - // In addition, either its function-body shall be = delete or = default or - // it shall satisfy the following constraints: +// This implements C++11 [dcl.constexpr]p3,4, as amended by DR1360. +bool Sema::CheckConstexprFunctionDecl(const FunctionDecl *NewFD) { + const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD); + if (MD && MD->isInstance()) { + // C++11 [dcl.constexpr]p4: + // The definition of a constexpr constructor shall satisfy the following + // constraints: // - the class shall not have any virtual base classes; - const CXXRecordDecl *RD = CD->getParent(); + const CXXRecordDecl *RD = MD->getParent(); if (RD->getNumVBases()) { - // Note, this is still illegal if the body is = default, since the - // implicit body does not satisfy the requirements of a constexpr - // constructor. We also reject cases where the body is = delete, as - // required by N3308. - if (CCK != CCK_Instantiation) { - Diag(NewFD->getLocation(), - CCK == CCK_Declaration ? diag::err_constexpr_virtual_base - : diag::note_constexpr_tmpl_virtual_base) - << RD->isStruct() << RD->getNumVBases(); - for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(), - E = RD->vbases_end(); I != E; ++I) - Diag(I->getSourceRange().getBegin(), - diag::note_constexpr_virtual_base_here) << I->getSourceRange(); - } + Diag(NewFD->getLocation(), diag::err_constexpr_virtual_base) + << isa<CXXConstructorDecl>(NewFD) << RD->isStruct() + << RD->getNumVBases(); + for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(), + E = RD->vbases_end(); I != E; ++I) + Diag(I->getLocStart(), + diag::note_constexpr_virtual_base_here) << I->getSourceRange(); return false; } - } else { - // C++0x [dcl.constexpr]p3: + } + + if (!isa<CXXConstructorDecl>(NewFD)) { + // C++11 [dcl.constexpr]p3: // The definition of a constexpr function shall satisfy the following // constraints: // - it shall not be virtual; const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(NewFD); if (Method && Method->isVirtual()) { - if (CCK != CCK_Instantiation) { - Diag(NewFD->getLocation(), - CCK == CCK_Declaration ? diag::err_constexpr_virtual - : diag::note_constexpr_tmpl_virtual); - - // If it's not obvious why this function is virtual, find an overridden - // function which uses the 'virtual' keyword. - const CXXMethodDecl *WrittenVirtual = Method; - while (!WrittenVirtual->isVirtualAsWritten()) - WrittenVirtual = *WrittenVirtual->begin_overridden_methods(); - if (WrittenVirtual != Method) - Diag(WrittenVirtual->getLocation(), - diag::note_overridden_virtual_function); - } + Diag(NewFD->getLocation(), diag::err_constexpr_virtual); + + // If it's not obvious why this function is virtual, find an overridden + // function which uses the 'virtual' keyword. + const CXXMethodDecl *WrittenVirtual = Method; + while (!WrittenVirtual->isVirtualAsWritten()) + WrittenVirtual = *WrittenVirtual->begin_overridden_methods(); + if (WrittenVirtual != Method) + Diag(WrittenVirtual->getLocation(), + diag::note_overridden_virtual_function); return false; } // - its return type shall be a literal type; QualType RT = NewFD->getResultType(); if (!RT->isDependentType() && - RequireLiteralType(NewFD->getLocation(), RT, CCK == CCK_Declaration ? - PDiag(diag::err_constexpr_non_literal_return) : - PDiag(), - /*AllowIncompleteType*/ true)) { - if (CCK == CCK_NoteNonConstexprInstantiation) - Diag(NewFD->getLocation(), - diag::note_constexpr_tmpl_non_literal_return) << RT; - return false; - } - - // - each of its parameter types shall be a literal type; - if (!CheckConstexprParameterTypes(*this, NewFD, CCK)) + RequireLiteralType(NewFD->getLocation(), RT, + PDiag(diag::err_constexpr_non_literal_return))) return false; } + // - each of its parameter types shall be a literal type; + if (!CheckConstexprParameterTypes(*this, NewFD)) + return false; + return true; } @@ -812,7 +811,11 @@ static void CheckConstexprCtorInitializer(Sema &SemaRef, bool &Diagnosed) { if (Field->isUnnamedBitfield()) return; - + + if (Field->isAnonymousStructOrUnion() && + Field->getType()->getAsCXXRecordDecl()->isEmpty()) + return; + if (!Inits.count(Field)) { if (!Diagnosed) { SemaRef.Diag(Dcl->getLocation(), diag::err_constexpr_ctor_missing_init); @@ -836,13 +839,13 @@ static void CheckConstexprCtorInitializer(Sema &SemaRef, /// \return true if the body is OK, false if we have diagnosed a problem. bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) { if (isa<CXXTryStmt>(Body)) { - // C++0x [dcl.constexpr]p3: + // C++11 [dcl.constexpr]p3: // The definition of a constexpr function shall satisfy the following // constraints: [...] // - its function-body shall be = delete, = default, or a // compound-statement // - // C++0x [dcl.constexpr]p4: + // C++11 [dcl.constexpr]p4: // In the definition of a constexpr constructor, [...] // - its function-body shall not be a function-try-block; Diag(Body->getLocStart(), diag::err_constexpr_function_try_block) @@ -877,12 +880,6 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) { break; ReturnStmts.push_back((*BodyIt)->getLocStart()); - // FIXME - // - every constructor call and implicit conversion used in initializing - // the return value shall be one of those allowed in a constant - // expression. - // Deal with this as part of a general check that the function can produce - // a constant expression (for [dcl.constexpr]p5). continue; default: @@ -897,11 +894,14 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) { if (const CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Dcl)) { const CXXRecordDecl *RD = Constructor->getParent(); - // - every non-static data member and base class sub-object shall be - // initialized; + // DR1359: + // - every non-variant non-static data member and base class sub-object + // shall be initialized; + // - if the class is a non-empty union, or for each non-empty anonymous + // union member of a non-union class, exactly one non-static data member + // shall be initialized; if (RD->isUnion()) { - // DR1359: Exactly one member of a union shall be initialized. - if (Constructor->getNumCtorInitializers() == 0) { + if (Constructor->getNumCtorInitializers() == 0 && !RD->isEmpty()) { Diag(Dcl->getLocation(), diag::err_constexpr_union_ctor_no_init); return false; } @@ -943,20 +943,6 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) { return false; } } - - // FIXME - // - every constructor involved in initializing non-static data members - // and base class sub-objects shall be a constexpr constructor; - // - every assignment-expression that is an initializer-clause appearing - // directly or indirectly within a brace-or-equal-initializer for - // a non-static data member that is not named by a mem-initializer-id - // shall be a constant expression; and - // - every implicit conversion used in converting a constructor argument - // to the corresponding parameter type and converting - // a full-expression to the corresponding member type shall be one of - // those allowed in a constant expression. - // Deal with these as part of a general check that the function can produce - // a constant expression (for [dcl.constexpr]p5). } else { if (ReturnStmts.empty()) { Diag(Dcl->getLocation(), diag::err_constexpr_body_no_return); @@ -970,6 +956,25 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) { } } + // C++11 [dcl.constexpr]p5: + // if no function argument values exist such that the function invocation + // substitution would produce a constant expression, the program is + // ill-formed; no diagnostic required. + // C++11 [dcl.constexpr]p3: + // - every constructor call and implicit conversion used in initializing the + // return value shall be one of those allowed in a constant expression. + // 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; + if (!Expr::isPotentialConstantExpr(Dcl, Diags)) { + Diag(Dcl->getLocation(), diag::err_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; + } + return true; } @@ -979,7 +984,7 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) { /// the innermost class. bool Sema::isCurrentClassName(const IdentifierInfo &II, Scope *, const CXXScopeSpec *SS) { - assert(getLangOptions().CPlusPlus && "No class names in C!"); + assert(getLangOpts().CPlusPlus && "No class names in C!"); CXXRecordDecl *CurDecl; if (SS && SS->isSet() && !SS->isInvalid()) { @@ -1133,13 +1138,15 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases, QualType NewBaseType = Context.getCanonicalType(Bases[idx]->getType()); NewBaseType = NewBaseType.getLocalUnqualifiedType(); - if (KnownBaseTypes[NewBaseType]) { + + CXXBaseSpecifier *&KnownBase = KnownBaseTypes[NewBaseType]; + if (KnownBase) { // C++ [class.mi]p3: // A class shall not be specified as a direct base class of a // derived class more than once. - Diag(Bases[idx]->getSourceRange().getBegin(), + Diag(Bases[idx]->getLocStart(), diag::err_duplicate_base_class) - << KnownBaseTypes[NewBaseType]->getType() + << KnownBase->getType() << Bases[idx]->getSourceRange(); // Delete the duplicate base class specifier; we're going to @@ -1149,8 +1156,12 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases, Invalid = true; } else { // Okay, add this new base class. - KnownBaseTypes[NewBaseType] = Bases[idx]; + KnownBase = Bases[idx]; Bases[NumGoodBases++] = Bases[idx]; + if (const RecordType *Record = NewBaseType->getAs<RecordType>()) + if (const CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl())) + if (RD->hasAttr<WeakAttr>()) + Class->addAttr(::new (Context) WeakAttr(SourceRange(), Context)); } } @@ -1190,7 +1201,7 @@ static CXXRecordDecl *GetClassForType(QualType T) { /// \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 (!getLangOptions().CPlusPlus) + if (!getLangOpts().CPlusPlus) return false; CXXRecordDecl *DerivedRD = GetClassForType(Derived); @@ -1208,7 +1219,7 @@ bool Sema::IsDerivedFrom(QualType Derived, QualType Base) { /// \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, CXXBasePaths &Paths) { - if (!getLangOptions().CPlusPlus) + if (!getLangOpts().CPlusPlus) return false; CXXRecordDecl *DerivedRD = GetClassForType(Derived); @@ -1441,7 +1452,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, // For anonymous bitfields, the location should point to the type. if (Loc.isInvalid()) - Loc = D.getSourceRange().getBegin(); + Loc = D.getLocStart(); Expr *BitWidth = static_cast<Expr*>(BW); @@ -1527,14 +1538,12 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, // class X { // int X::member; // }; - DeclContext *DC = 0; - if ((DC = computeDeclContext(SS, false)) && DC->Equals(CurContext)) - Diag(D.getIdentifierLoc(), diag::warn_member_extra_qualification) - << Name << FixItHint::CreateRemoval(SS.getRange()); + if (DeclContext *DC = computeDeclContext(SS, false)) + diagnoseQualifiedDeclaration(SS, DC, Name, D.getIdentifierLoc()); else Diag(D.getIdentifierLoc(), diag::err_member_qualification) << Name << SS.getRange(); - + SS.clear(); } @@ -1631,11 +1640,26 @@ Sema::ActOnCXXInClassMemberInitializer(Decl *D, SourceLocation EqualLoc, return; } + if (DiagnoseUnexpandedParameterPack(InitExpr, UPPC_Initializer)) { + FD->setInvalidDecl(); + FD->removeInClassInitializer(); + return; + } + ExprResult Init = InitExpr; if (!FD->getType()->isDependentType() && !InitExpr->isTypeDependent()) { - // FIXME: if there is no EqualLoc, this is list-initialization. - Init = PerformCopyInitialization( - InitializedEntity::InitializeMember(FD), EqualLoc, InitExpr); + if (isa<InitListExpr>(InitExpr) && isStdInitializerList(FD->getType(), 0)) { + Diag(FD->getLocation(), diag::warn_dangling_std_initializer_list) + << /*at end of ctor*/1 << InitExpr->getSourceRange(); + } + Expr **Inits = &InitExpr; + unsigned NumInits = 1; + InitializedEntity Entity = InitializedEntity::InitializeMember(FD); + InitializationKind Kind = EqualLoc.isInvalid() + ? InitializationKind::CreateDirectList(InitExpr->getLocStart()) + : InitializationKind::CreateCopy(InitExpr->getLocStart(), EqualLoc); + InitializationSequence Seq(*this, Entity, Kind, Inits, NumInits); + Init = Seq.Perform(*this, Entity, Kind, MultiExprArg(Inits, NumInits)); if (Init.isInvalid()) { FD->setInvalidDecl(); return; @@ -1710,11 +1734,13 @@ Sema::ActOnMemInitializer(Decl *ConstructorD, CXXScopeSpec &SS, IdentifierInfo *MemberOrBase, ParsedType TemplateTypeTy, + const DeclSpec &DS, SourceLocation IdLoc, Expr *InitList, SourceLocation EllipsisLoc) { return BuildMemInitializer(ConstructorD, S, SS, MemberOrBase, TemplateTypeTy, - IdLoc, MultiInitializer(InitList), EllipsisLoc); + DS, IdLoc, InitList, + EllipsisLoc); } /// \brief Handle a C++ member initializer using parentheses syntax. @@ -1724,15 +1750,41 @@ Sema::ActOnMemInitializer(Decl *ConstructorD, CXXScopeSpec &SS, IdentifierInfo *MemberOrBase, ParsedType TemplateTypeTy, + const DeclSpec &DS, SourceLocation IdLoc, SourceLocation LParenLoc, Expr **Args, unsigned NumArgs, SourceLocation RParenLoc, SourceLocation EllipsisLoc) { + Expr *List = new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs, + RParenLoc); return BuildMemInitializer(ConstructorD, S, SS, MemberOrBase, TemplateTypeTy, - IdLoc, MultiInitializer(LParenLoc, Args, NumArgs, - RParenLoc), - EllipsisLoc); + DS, IdLoc, List, EllipsisLoc); +} + +namespace { + +// Callback to only accept typo corrections that can be a valid C++ member +// intializer: either a non-static field member or a base class. +class MemInitializerValidatorCCC : public CorrectionCandidateCallback { + public: + explicit MemInitializerValidatorCCC(CXXRecordDecl *ClassDecl) + : ClassDecl(ClassDecl) {} + + virtual bool ValidateCandidate(const TypoCorrection &candidate) { + if (NamedDecl *ND = candidate.getCorrectionDecl()) { + if (FieldDecl *Member = dyn_cast<FieldDecl>(ND)) + return Member->getDeclContext()->getRedeclContext()->Equals(ClassDecl); + else + return isa<TypeDecl>(ND); + } + return false; + } + + private: + CXXRecordDecl *ClassDecl; +}; + } /// \brief Handle a C++ member initializer. @@ -1742,8 +1794,9 @@ Sema::BuildMemInitializer(Decl *ConstructorD, CXXScopeSpec &SS, IdentifierInfo *MemberOrBase, ParsedType TemplateTypeTy, + const DeclSpec &DS, SourceLocation IdLoc, - const MultiInitializer &Args, + Expr *Init, SourceLocation EllipsisLoc) { if (!ConstructorD) return true; @@ -1774,28 +1827,18 @@ Sema::BuildMemInitializer(Decl *ConstructorD, // using a qualified name. ] if (!SS.getScopeRep() && !TemplateTypeTy) { // Look for a member, first. - FieldDecl *Member = 0; DeclContext::lookup_result Result = ClassDecl->lookup(MemberOrBase); if (Result.first != Result.second) { - Member = dyn_cast<FieldDecl>(*Result.first); - - if (Member) { - if (EllipsisLoc.isValid()) - Diag(EllipsisLoc, diag::err_pack_expansion_member_init) - << MemberOrBase << SourceRange(IdLoc, Args.getEndLoc()); - - return BuildMemberInitializer(Member, Args, IdLoc); - } - - // Handle anonymous union case. - if (IndirectFieldDecl* IndirectField - = dyn_cast<IndirectFieldDecl>(*Result.first)) { + ValueDecl *Member; + if ((Member = dyn_cast<FieldDecl>(*Result.first)) || + (Member = dyn_cast<IndirectFieldDecl>(*Result.first))) { if (EllipsisLoc.isValid()) Diag(EllipsisLoc, diag::err_pack_expansion_member_init) - << MemberOrBase << SourceRange(IdLoc, Args.getEndLoc()); + << MemberOrBase + << SourceRange(IdLoc, Init->getSourceRange().getEnd()); - return BuildMemberInitializer(IndirectField, Args, IdLoc); + return BuildMemberInitializer(Member, Init, IdLoc); } } } @@ -1805,6 +1848,8 @@ Sema::BuildMemInitializer(Decl *ConstructorD, if (TemplateTypeTy) { BaseType = GetTypeFromParser(TemplateTypeTy, &TInfo); + } else if (DS.getTypeSpecType() == TST_decltype) { + BaseType = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc()); } else { LookupResult R(*this, MemberOrBase, IdLoc, LookupOrdinaryName); LookupParsedName(R, S, &SS); @@ -1838,24 +1883,23 @@ Sema::BuildMemInitializer(Decl *ConstructorD, // If no results were found, try to correct typos. TypoCorrection Corr; + MemInitializerValidatorCCC Validator(ClassDecl); if (R.empty() && BaseType.isNull() && (Corr = CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S, &SS, - ClassDecl, false, CTC_NoKeywords))) { - std::string CorrectedStr(Corr.getAsString(getLangOptions())); - std::string CorrectedQuotedStr(Corr.getQuoted(getLangOptions())); + Validator, ClassDecl))) { + std::string CorrectedStr(Corr.getAsString(getLangOpts())); + std::string CorrectedQuotedStr(Corr.getQuoted(getLangOpts())); if (FieldDecl *Member = Corr.getCorrectionDeclAs<FieldDecl>()) { - if (Member->getDeclContext()->getRedeclContext()->Equals(ClassDecl)) { - // We have found a non-static data member with a similar - // name to what was typed; complain and initialize that - // member. - Diag(R.getNameLoc(), diag::err_mem_init_not_member_or_class_suggest) - << MemberOrBase << true << CorrectedQuotedStr - << FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr); - Diag(Member->getLocation(), diag::note_previous_decl) - << CorrectedQuotedStr; - - return BuildMemberInitializer(Member, Args, IdLoc); - } + // We have found a non-static data member with a similar + // name to what was typed; complain and initialize that + // member. + Diag(R.getNameLoc(), diag::err_mem_init_not_member_or_class_suggest) + << MemberOrBase << true << CorrectedQuotedStr + << FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr); + Diag(Member->getLocation(), diag::note_previous_decl) + << CorrectedQuotedStr; + + return BuildMemberInitializer(Member, Init, IdLoc); } else if (TypeDecl *Type = Corr.getCorrectionDeclAs<TypeDecl>()) { const CXXBaseSpecifier *DirectBaseSpec; const CXXBaseSpecifier *VirtualBaseSpec; @@ -1871,7 +1915,7 @@ Sema::BuildMemInitializer(Decl *ConstructorD, const CXXBaseSpecifier *BaseSpec = DirectBaseSpec? DirectBaseSpec : VirtualBaseSpec; - Diag(BaseSpec->getSourceRange().getBegin(), + Diag(BaseSpec->getLocStart(), diag::note_base_class_specified_here) << BaseSpec->getType() << BaseSpec->getSourceRange(); @@ -1883,7 +1927,7 @@ Sema::BuildMemInitializer(Decl *ConstructorD, if (!TyD && BaseType.isNull()) { Diag(IdLoc, diag::err_mem_init_not_member_or_class) - << MemberOrBase << SourceRange(IdLoc, Args.getEndLoc()); + << MemberOrBase << SourceRange(IdLoc,Init->getSourceRange().getEnd()); return true; } } @@ -1903,7 +1947,7 @@ Sema::BuildMemInitializer(Decl *ConstructorD, if (!TInfo) TInfo = Context.getTrivialTypeSourceInfo(BaseType, IdLoc); - return BuildBaseInitializer(BaseType, TInfo, Args, ClassDecl, EllipsisLoc); + return BuildBaseInitializer(BaseType, TInfo, Init, ClassDecl, EllipsisLoc); } /// Checks a member initializer expression for cases where reference (or @@ -2030,14 +2074,16 @@ static bool InitExprContainsUninitializedFields(const Stmt *S, } MemInitResult -Sema::BuildMemberInitializer(ValueDecl *Member, - const MultiInitializer &Args, +Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init, SourceLocation IdLoc) { FieldDecl *DirectMember = dyn_cast<FieldDecl>(Member); IndirectFieldDecl *IndirectMember = dyn_cast<IndirectFieldDecl>(Member); assert((DirectMember || IndirectMember) && "Member must be a FieldDecl or IndirectFieldDecl"); + if (DiagnoseUnexpandedParameterPack(Init, UPPC_Initializer)) + return true; + if (Member->isInvalidDecl()) return true; @@ -2045,13 +2091,19 @@ Sema::BuildMemberInitializer(ValueDecl *Member, // foo(foo) // where foo is not also a parameter to the constructor. // TODO: implement -Wuninitialized and fold this into that framework. - for (MultiInitializer::iterator I = Args.begin(), E = Args.end(); - I != E; ++I) { + Expr **Args; + unsigned NumArgs; + if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) { + Args = ParenList->getExprs(); + NumArgs = ParenList->getNumExprs(); + } else { + InitListExpr *InitList = cast<InitListExpr>(Init); + Args = InitList->getInits(); + NumArgs = InitList->getNumInits(); + } + for (unsigned i = 0; i < NumArgs; ++i) { SourceLocation L; - Expr *Arg = *I; - if (DesignatedInitExpr *DIE = dyn_cast<DesignatedInitExpr>(Arg)) - Arg = DIE->getInit(); - if (InitExprContainsUninitializedFields(Arg, Member, &L)) { + if (InitExprContainsUninitializedFields(Args[i], Member, &L)) { // FIXME: Return true in the case when other fields are used before being // uninitialized. For example, let this field be the i'th field. When // initializing the i'th field, throw a warning if any of the >= i'th @@ -2062,29 +2114,43 @@ Sema::BuildMemberInitializer(ValueDecl *Member, } } - bool HasDependentArg = Args.isTypeDependent(); + SourceRange InitRange = Init->getSourceRange(); - Expr *Init; - if (Member->getType()->isDependentType() || HasDependentArg) { + if (Member->getType()->isDependentType() || Init->isTypeDependent()) { // Can't check initialization for a member of dependent type or when // any of the arguments are type-dependent expressions. - Init = Args.CreateInitExpr(Context,Member->getType().getNonReferenceType()); - DiscardCleanupsInEvaluationContext(); } else { + bool InitList = false; + if (isa<InitListExpr>(Init)) { + InitList = true; + Args = &Init; + NumArgs = 1; + + if (isStdInitializerList(Member->getType(), 0)) { + Diag(IdLoc, diag::warn_dangling_std_initializer_list) + << /*at end of ctor*/1 << InitRange; + } + } + // Initialize the member. InitializedEntity MemberEntity = DirectMember ? InitializedEntity::InitializeMember(DirectMember, 0) : InitializedEntity::InitializeMember(IndirectMember, 0); InitializationKind Kind = - InitializationKind::CreateDirect(IdLoc, Args.getStartLoc(), - Args.getEndLoc()); - - ExprResult MemberInit = Args.PerformInit(*this, MemberEntity, Kind); + InitList ? InitializationKind::CreateDirectList(IdLoc) + : InitializationKind::CreateDirect(IdLoc, InitRange.getBegin(), + InitRange.getEnd()); + + InitializationSequence InitSeq(*this, MemberEntity, Kind, Args, NumArgs); + ExprResult MemberInit = InitSeq.Perform(*this, MemberEntity, Kind, + MultiExprArg(*this, Args, NumArgs), + 0); if (MemberInit.isInvalid()) return true; - CheckImplicitConversions(MemberInit.get(), Args.getStartLoc()); + CheckImplicitConversions(MemberInit.get(), + InitRange.getBegin()); // C++0x [class.base.init]p7: // The initialization of each base and member constitutes a @@ -2095,14 +2161,13 @@ Sema::BuildMemberInitializer(ValueDecl *Member, // If we are in a dependent context, template instantiation will // perform this type-checking again. Just save the arguments that we - // received in a ParenListExpr. + // 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()) { - Init = Args.CreateInitExpr(Context, - Member->getType().getNonReferenceType()); + // The existing Init will do fine. } else { Init = MemberInit.get(); CheckForDanglingReferenceOrPointer(*this, Member, Init, IdLoc); @@ -2110,43 +2175,53 @@ Sema::BuildMemberInitializer(ValueDecl *Member, } if (DirectMember) { - return new (Context) CXXCtorInitializer(Context, DirectMember, - IdLoc, Args.getStartLoc(), - Init, Args.getEndLoc()); + return new (Context) CXXCtorInitializer(Context, DirectMember, IdLoc, + InitRange.getBegin(), Init, + InitRange.getEnd()); } else { - return new (Context) CXXCtorInitializer(Context, IndirectMember, - IdLoc, Args.getStartLoc(), - Init, Args.getEndLoc()); + return new (Context) CXXCtorInitializer(Context, IndirectMember, IdLoc, + InitRange.getBegin(), Init, + InitRange.getEnd()); } } MemInitResult -Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, - const MultiInitializer &Args, - SourceLocation NameLoc, +Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init, CXXRecordDecl *ClassDecl) { - SourceLocation Loc = TInfo->getTypeLoc().getLocalSourceRange().getBegin(); + SourceLocation NameLoc = TInfo->getTypeLoc().getLocalSourceRange().getBegin(); if (!LangOpts.CPlusPlus0x) - return Diag(Loc, diag::err_delegation_0x_only) + return Diag(NameLoc, diag::err_delegating_ctor) << TInfo->getTypeLoc().getLocalSourceRange(); + Diag(NameLoc, diag::warn_cxx98_compat_delegating_ctor); + bool InitList = true; + Expr **Args = &Init; + unsigned NumArgs = 1; + if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) { + InitList = false; + Args = ParenList->getExprs(); + NumArgs = ParenList->getNumExprs(); + } + + SourceRange InitRange = Init->getSourceRange(); // Initialize the object. InitializedEntity DelegationEntity = InitializedEntity::InitializeDelegation( QualType(ClassDecl->getTypeForDecl(), 0)); InitializationKind Kind = - InitializationKind::CreateDirect(NameLoc, Args.getStartLoc(), - Args.getEndLoc()); - - ExprResult DelegationInit = Args.PerformInit(*this, DelegationEntity, Kind); + InitList ? InitializationKind::CreateDirectList(NameLoc) + : InitializationKind::CreateDirect(NameLoc, InitRange.getBegin(), + InitRange.getEnd()); + InitializationSequence InitSeq(*this, DelegationEntity, Kind, Args, NumArgs); + ExprResult DelegationInit = InitSeq.Perform(*this, DelegationEntity, Kind, + MultiExprArg(*this, Args,NumArgs), + 0); if (DelegationInit.isInvalid()) return true; - CXXConstructExpr *ConExpr = cast<CXXConstructExpr>(DelegationInit.get()); - CXXConstructorDecl *Constructor - = ConExpr->getConstructor(); - assert(Constructor && "Delegating constructor with no target?"); + assert(cast<CXXConstructExpr>(DelegationInit.get())->getConstructor() && + "Delegating constructor with no target?"); - CheckImplicitConversions(DelegationInit.get(), Args.getStartLoc()); + CheckImplicitConversions(DelegationInit.get(), InitRange.getBegin()); // C++0x [class.base.init]p7: // The initialization of each base and member constitutes a @@ -2155,20 +2230,15 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, if (DelegationInit.isInvalid()) return true; - assert(!CurContext->isDependentContext()); - return new (Context) CXXCtorInitializer(Context, Loc, Args.getStartLoc(), - Constructor, + return new (Context) CXXCtorInitializer(Context, TInfo, InitRange.getBegin(), DelegationInit.takeAs<Expr>(), - Args.getEndLoc()); + InitRange.getEnd()); } MemInitResult Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, - const MultiInitializer &Args, - CXXRecordDecl *ClassDecl, + Expr *Init, CXXRecordDecl *ClassDecl, SourceLocation EllipsisLoc) { - bool HasDependentArg = Args.isTypeDependent(); - SourceLocation BaseLoc = BaseTInfo->getTypeLoc().getLocalSourceRange().getBegin(); @@ -2182,13 +2252,14 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, // of that class, the mem-initializer is ill-formed. A // mem-initializer-list can initialize a base class using any // name that denotes that base class type. - bool Dependent = BaseType->isDependentType() || HasDependentArg; + bool Dependent = BaseType->isDependentType() || Init->isTypeDependent(); + SourceRange InitRange = Init->getSourceRange(); if (EllipsisLoc.isValid()) { // This is a pack expansion. if (!BaseType->containsUnexpandedParameterPack()) { Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) - << SourceRange(BaseLoc, Args.getEndLoc()); + << SourceRange(BaseLoc, InitRange.getEnd()); EllipsisLoc = SourceLocation(); } @@ -2197,7 +2268,7 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, if (DiagnoseUnexpandedParameterPack(BaseLoc, BaseTInfo, UPPC_Initializer)) return true; - if (Args.DiagnoseUnexpandedParameterPack(*this)) + if (DiagnoseUnexpandedParameterPack(Init, UPPC_Initializer)) return true; } @@ -2207,7 +2278,7 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, if (!Dependent) { if (Context.hasSameUnqualifiedType(QualType(ClassDecl->getTypeForDecl(),0), BaseType)) - return BuildDelegatingInitializer(BaseTInfo, Args, BaseLoc, ClassDecl); + return BuildDelegatingInitializer(BaseTInfo, Init, ClassDecl); FindBaseInitializer(*this, ClassDecl, BaseType, DirectBaseSpec, VirtualBaseSpec); @@ -2232,16 +2303,12 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, } if (Dependent) { - // Can't check initialization for a base of dependent type or when - // any of the arguments are type-dependent expressions. - Expr *BaseInit = Args.CreateInitExpr(Context, BaseType); - DiscardCleanupsInEvaluationContext(); return new (Context) CXXCtorInitializer(Context, BaseTInfo, /*IsVirtual=*/false, - Args.getStartLoc(), BaseInit, - Args.getEndLoc(), EllipsisLoc); + InitRange.getBegin(), Init, + InitRange.getEnd(), EllipsisLoc); } // C++ [base.class.init]p2: @@ -2252,23 +2319,34 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, return Diag(BaseLoc, diag::err_base_init_direct_and_virtual) << BaseType << BaseTInfo->getTypeLoc().getLocalSourceRange(); - CXXBaseSpecifier *BaseSpec - = const_cast<CXXBaseSpecifier *>(DirectBaseSpec); + CXXBaseSpecifier *BaseSpec = const_cast<CXXBaseSpecifier *>(DirectBaseSpec); if (!BaseSpec) BaseSpec = const_cast<CXXBaseSpecifier *>(VirtualBaseSpec); // Initialize the base. + bool InitList = true; + Expr **Args = &Init; + unsigned NumArgs = 1; + if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) { + InitList = false; + Args = ParenList->getExprs(); + NumArgs = ParenList->getNumExprs(); + } + InitializedEntity BaseEntity = InitializedEntity::InitializeBase(Context, BaseSpec, VirtualBaseSpec); - InitializationKind Kind = - InitializationKind::CreateDirect(BaseLoc, Args.getStartLoc(), - Args.getEndLoc()); - - ExprResult BaseInit = Args.PerformInit(*this, BaseEntity, Kind); + InitializationKind Kind = + InitList ? InitializationKind::CreateDirectList(BaseLoc) + : InitializationKind::CreateDirect(BaseLoc, InitRange.getBegin(), + InitRange.getEnd()); + InitializationSequence InitSeq(*this, BaseEntity, Kind, Args, NumArgs); + ExprResult BaseInit = InitSeq.Perform(*this, BaseEntity, Kind, + MultiExprArg(*this, Args, NumArgs), + 0); if (BaseInit.isInvalid()) return true; - CheckImplicitConversions(BaseInit.get(), Args.getStartLoc()); + CheckImplicitConversions(BaseInit.get(), InitRange.getBegin()); // C++0x [class.base.init]p7: // The initialization of each base and member constitutes a @@ -2285,13 +2363,13 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, // 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()) - BaseInit = Owned(Args.CreateInitExpr(Context, BaseType)); + BaseInit = Owned(Init); return new (Context) CXXCtorInitializer(Context, BaseTInfo, BaseSpec->isVirtual(), - Args.getStartLoc(), + InitRange.getBegin(), BaseInit.takeAs<Expr>(), - Args.getEndLoc(), EllipsisLoc); + InitRange.getEnd(), EllipsisLoc); } // Create a static_cast\<T&&>(expr). @@ -2342,12 +2420,15 @@ BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, bool Moving = ImplicitInitKind == IIK_Move; ParmVarDecl *Param = Constructor->getParamDecl(0); QualType ParamType = Param->getType().getNonReferenceType(); - + Expr *CopyCtorArg = - DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(), Param, + DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(), + SourceLocation(), Param, false, Constructor->getLocation(), ParamType, VK_LValue, 0); + SemaRef.MarkDeclRefReferenced(cast<DeclRefExpr>(CopyCtorArg)); + // Cast to the base class to avoid ambiguities. QualType ArgTy = SemaRef.Context.getQualifiedType(BaseSpec->getType().getUnqualifiedType(), @@ -2415,11 +2496,14 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, // Suppress copying zero-width bitfields. if (Field->isBitField() && Field->getBitWidthValue(SemaRef.Context) == 0) return false; - + Expr *MemberExprBase = - DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(), Param, + DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(), + SourceLocation(), Param, false, Loc, ParamType, VK_LValue, 0); + SemaRef.MarkDeclRefReferenced(cast<DeclRefExpr>(MemberExprBase)); + if (Moving) { MemberExprBase = CastForMoving(SemaRef, MemberExprBase); } @@ -2436,6 +2520,7 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, ParamType, Loc, /*IsArrow=*/false, SS, + /*TemplateKWLoc=*/SourceLocation(), /*FirstQualifierInScope=*/0, MemberLookup, /*TemplateArgs=*/0); @@ -2463,7 +2548,7 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, // Create the iteration variable for this array index. IdentifierInfo *IterationVarName = 0; { - llvm::SmallString<8> Str; + SmallString<8> Str; llvm::raw_svector_ostream OS(Str); OS << "__i" << IndexVariables.size(); IterationVarName = &SemaRef.Context.Idents.get(OS.str()); @@ -2477,9 +2562,12 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, // Create a reference to the iteration variable. ExprResult IterationVarRef - = SemaRef.BuildDeclRefExpr(IterationVar, SizeType, VK_RValue, Loc); + = SemaRef.BuildDeclRefExpr(IterationVar, SizeType, VK_LValue, Loc); assert(!IterationVarRef.isInvalid() && "Reference to invented variable cannot fail!"); + IterationVarRef = SemaRef.DefaultLvalueConversion(IterationVarRef.take()); + assert(!IterationVarRef.isInvalid() && + "Conversion of invented variable cannot fail!"); // Subscript the array with this iteration variable. CtorArg = SemaRef.CreateBuiltinArraySubscriptExpr(CtorArg.take(), Loc, @@ -2597,7 +2685,7 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, } } - if (SemaRef.getLangOptions().ObjCAutoRefCount && + if (SemaRef.getLangOpts().ObjCAutoRefCount && FieldBaseElementType->isObjCRetainableType() && FieldBaseElementType.getObjCLifetime() != Qualifiers::OCL_None && FieldBaseElementType.getObjCLifetime() != Qualifiers::OCL_ExplicitNone) { @@ -2635,6 +2723,19 @@ struct BaseAndFieldInfo { else IIK = IIK_Default; } + + bool isImplicitCopyOrMove() const { + switch (IIK) { + case IIK_Copy: + case IIK_Move: + return true; + + case IIK_Default: + return false; + } + + llvm_unreachable("Invalid ImplicitInitializerKind!"); + } }; } @@ -2651,6 +2752,22 @@ static bool isWithinAnonymousUnion(IndirectFieldDecl *F) { return false; } +/// \brief Determine whether the given type is an incomplete or zero-lenfgth +/// array type. +static bool isIncompleteOrZeroLengthArrayType(ASTContext &Context, QualType T) { + if (T->isIncompleteArrayType()) + return true; + + while (const ConstantArrayType *ArrayT = Context.getAsConstantArrayType(T)) { + if (!ArrayT->getSize()) + return true; + + T = ArrayT->getElementType(); + } + + return false; +} + static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info, FieldDecl *Field, IndirectFieldDecl *Indirect = 0) { @@ -2664,7 +2781,7 @@ static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info, // C++0x [class.base.init]p8: if the entity is a non-static data member that // has a brace-or-equal-initializer, the entity is initialized as specified // in [dcl.init]. - if (Field->hasInClassInitializer()) { + if (Field->hasInClassInitializer() && !Info.isImplicitCopyOrMove()) { CXXCtorInitializer *Init; if (Indirect) Init = new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, Indirect, @@ -2686,6 +2803,10 @@ static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info, (Indirect && isWithinAnonymousUnion(Indirect))) return false; + // Don't initialize incomplete or zero-length arrays. + if (isIncompleteOrZeroLengthArrayType(SemaRef.Context, Field->getType())) + return false; + // Don't try to build an implicit initializer if there were semantic // errors in any of the initializers (and therefore we might be // missing some that the user actually wrote). @@ -2714,7 +2835,7 @@ Sema::SetDelegatingInitializer(CXXConstructorDecl *Constructor, Constructor->setCtorInitializers(initializer); if (CXXDestructorDecl *Dtor = LookupDestructor(Constructor->getParent())) { - MarkDeclarationReferenced(Initializer->getSourceLocation(), Dtor); + MarkFunctionReferenced(Initializer->getSourceLocation(), Dtor); DiagnoseUseOfDecl(Dtor, Initializer->getSourceLocation()); } @@ -2824,13 +2945,7 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, // initialized. if (F->isUnnamedBitfield()) continue; - - if (F->getType()->isIncompleteArrayType()) { - assert(ClassDecl->hasFlexibleArrayMember() && - "Incomplete array type is not valid"); - continue; - } - + // If we're not generating the implicit copy/move constructor, then we'll // handle anonymous struct/union fields based on their individual // indirect fields. @@ -2997,12 +3112,12 @@ DiagnoseBaseOrMemInitializerOrder(Sema &SemaRef, if (PrevInit->isAnyMemberInitializer()) D << 0 << PrevInit->getAnyMember()->getDeclName(); else - D << 1 << PrevInit->getBaseClassInfo()->getType(); + D << 1 << PrevInit->getTypeSourceInfo()->getType(); if (Init->isAnyMemberInitializer()) D << 0 << Init->getAnyMember()->getDeclName(); else - D << 1 << Init->getBaseClassInfo()->getType(); + D << 1 << Init->getTypeSourceInfo()->getType(); // Move back to the initializer's location in the ideal list. for (IdealIndex = 0; IdealIndex != NumIdealInits; ++IdealIndex) @@ -3053,11 +3168,9 @@ bool CheckRedundantUnionInit(Sema &S, RedundantUnionMap &Unions) { FieldDecl *Field = Init->getAnyMember(); RecordDecl *Parent = Field->getParent(); - if (!Parent->isAnonymousStructOrUnion()) - return false; - NamedDecl *Child = Field; - do { + + while (Parent->isAnonymousStructOrUnion() || Parent->isUnion()) { if (Parent->isUnion()) { UnionEntry &En = Unions[Parent]; if (En.first && En.first != Child) { @@ -3068,15 +3181,18 @@ bool CheckRedundantUnionInit(Sema &S, S.Diag(En.second->getSourceLocation(), diag::note_previous_initializer) << 0 << En.second->getSourceRange(); return true; - } else if (!En.first) { + } + if (!En.first) { En.first = Child; En.second = Init; } + if (!Parent->isAnonymousStructOrUnion()) + return false; } Child = Parent; Parent = cast<RecordDecl>(Parent->getDeclContext()); - } while (Parent->isAnonymousStructOrUnion()); + } return false; } @@ -3171,6 +3287,11 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location, FieldDecl *Field = *I; if (Field->isInvalidDecl()) continue; + + // Don't destroy incomplete or zero-length arrays. + if (isIncompleteOrZeroLengthArrayType(Context, Field->getType())) + continue; + QualType FieldType = Context.getBaseElementType(Field->getType()); const RecordType* RT = FieldType->getAs<RecordType>(); @@ -3180,7 +3301,10 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location, CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl()); if (FieldClassDecl->isInvalidDecl()) continue; - if (FieldClassDecl->hasTrivialDestructor()) + if (FieldClassDecl->hasIrrelevantDestructor()) + continue; + // The destructor for an implicit anonymous union member is never invoked. + if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion()) continue; CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl); @@ -3190,7 +3314,8 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location, << Field->getDeclName() << FieldType); - MarkDeclarationReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor)); + MarkFunctionReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor)); + DiagnoseUseOfDecl(Dtor, Location); } llvm::SmallPtrSet<const RecordType *, 8> DirectVirtualBases; @@ -3209,20 +3334,21 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location, // If our base class is invalid, we probably can't get its dtor anyway. if (BaseClassDecl->isInvalidDecl()) continue; - // Ignore trivial destructors. - if (BaseClassDecl->hasTrivialDestructor()) + if (BaseClassDecl->hasIrrelevantDestructor()) continue; CXXDestructorDecl *Dtor = LookupDestructor(BaseClassDecl); assert(Dtor && "No dtor found for BaseClassDecl!"); // FIXME: caret should be on the start of the class name - CheckDestructorAccess(Base->getSourceRange().getBegin(), Dtor, + CheckDestructorAccess(Base->getLocStart(), Dtor, PDiag(diag::err_access_dtor_base) << Base->getType() - << Base->getSourceRange()); + << Base->getSourceRange(), + Context.getTypeDeclType(ClassDecl)); - MarkDeclarationReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor)); + MarkFunctionReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor)); + DiagnoseUseOfDecl(Dtor, Location); } // Virtual bases. @@ -3230,7 +3356,7 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location, E = ClassDecl->vbases_end(); VBase != E; ++VBase) { // Bases are always records in a well-formed non-dependent class. - const RecordType *RT = VBase->getType()->getAs<RecordType>(); + const RecordType *RT = VBase->getType()->castAs<RecordType>(); // Ignore direct virtual bases. if (DirectVirtualBases.count(RT)) @@ -3240,17 +3366,18 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location, // If our base class is invalid, we probably can't get its dtor anyway. if (BaseClassDecl->isInvalidDecl()) continue; - // Ignore trivial destructors. - if (BaseClassDecl->hasTrivialDestructor()) + if (BaseClassDecl->hasIrrelevantDestructor()) continue; CXXDestructorDecl *Dtor = LookupDestructor(BaseClassDecl); assert(Dtor && "No dtor found for BaseClassDecl!"); CheckDestructorAccess(ClassDecl->getLocation(), Dtor, PDiag(diag::err_access_dtor_vbase) - << VBase->getType()); + << VBase->getType(), + Context.getTypeDeclType(ClassDecl)); - MarkDeclarationReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor)); + MarkFunctionReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor)); + DiagnoseUseOfDecl(Dtor, Location); } } @@ -3273,7 +3400,7 @@ bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, const PartialDiagnostic &PD) { - if (!getLangOptions().CPlusPlus) + if (!getLangOpts().CPlusPlus) return false; if (const ArrayType *AT = Context.getAsArrayType(T)) @@ -3538,7 +3665,8 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { // complain about any non-static data members of reference or const scalar // type, since they will never get initializers. if (!Record->isInvalidDecl() && !Record->isDependentType() && - !Record->isAggregate() && !Record->hasUserDeclaredConstructor()) { + !Record->isAggregate() && !Record->hasUserDeclaredConstructor() && + !Record->isLambda()) { bool Complained = false; for (RecordDecl::field_iterator F = Record->field_begin(), FEnd = Record->field_end(); @@ -3609,9 +3737,6 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { // const. [...] The class of which that function is a member shall be // a literal type. // - // It's fine to diagnose constructors here too: such constructors cannot - // produce a constant expression, so are ill-formed (no diagnostic required). - // // 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. @@ -3620,16 +3745,14 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { for (CXXRecordDecl::method_iterator M = Record->method_begin(), MEnd = Record->method_end(); M != MEnd; ++M) { - if ((*M)->isConstexpr()) { + if (M->isConstexpr() && M->isInstance() && !isa<CXXConstructorDecl>(*M)) { switch (Record->getTemplateSpecializationKind()) { case TSK_ImplicitInstantiation: case TSK_ExplicitInstantiationDeclaration: case TSK_ExplicitInstantiationDefinition: // If a template instantiates to a non-literal type, but its members // instantiate to constexpr functions, the template is technically - // ill-formed, but we allow it for sanity. Such members are treated as - // non-constexpr. - (*M)->setConstexpr(false); + // ill-formed, but we allow it for sanity. continue; case TSK_Undeclared: @@ -3725,6 +3848,21 @@ void Sema::CheckExplicitlyDefaultedDefaultConstructor(CXXConstructorDecl *CD) { *ExceptionType = Context.getFunctionType( Context.VoidTy, 0, 0, EPI)->getAs<FunctionProtoType>(); + // 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, + // Do not apply this rule to templates, since core issue 1358 makes such + // functions always instantiate to constexpr functions. + if (CD->isConstexpr() && + CD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) { + if (!CD->getParent()->defaultedDefaultConstructorIsConstexpr()) { + Diag(CD->getLocStart(), diag::err_incorrect_defaulted_constexpr) + << CXXDefaultConstructor; + HadError = true; + } + } + // and may have an explicit exception-specification only if it is compatible + // with the exception-specification on the implicit declaration. if (CtorType->hasExceptionSpec()) { if (CheckEquivalentExceptionSpec( PDiag(diag::err_incorrect_defaulted_exception_spec) @@ -3734,11 +3872,24 @@ void Sema::CheckExplicitlyDefaultedDefaultConstructor(CXXConstructorDecl *CD) { CtorType, CD->getLocation())) { HadError = true; } - } else if (First) { - // We set the declaration to have the computed exception spec here. - // We know there are no parameters. + } + + // If a function is explicitly defaulted on its first declaration, + if (First) { + // -- it is implicitly considered to be constexpr if the implicit + // definition would be, + CD->setConstexpr(CD->getParent()->defaultedDefaultConstructorIsConstexpr()); + + // -- it is implicitly considered to have the same + // exception-specification as if it had been implicitly declared + // + // FIXME: a compatible, but different, explicit exception specification + // will be silently overridden. We should issue a warning if this happens. EPI.ExtInfo = CtorType->getExtInfo(); - CD->setType(Context.getFunctionType(Context.VoidTy, 0, 0, EPI)); + + // Such a function is also trivial if the implicitly-declared function + // would have been. + CD->setTrivial(CD->getParent()->hasTrivialDefaultConstructor()); } if (HadError) { @@ -3792,6 +3943,21 @@ void Sema::CheckExplicitlyDefaultedCopyConstructor(CXXConstructorDecl *CD) { HadError = true; } + // 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, + // Do not apply this rule to templates, since core issue 1358 makes such + // functions always instantiate to constexpr functions. + if (CD->isConstexpr() && + CD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) { + if (!CD->getParent()->defaultedCopyConstructorIsConstexpr()) { + Diag(CD->getLocStart(), diag::err_incorrect_defaulted_constexpr) + << CXXCopyConstructor; + HadError = true; + } + } + // and may have an explicit exception-specification only if it is compatible + // with the exception-specification on the implicit declaration. if (CtorType->hasExceptionSpec()) { if (CheckEquivalentExceptionSpec( PDiag(diag::err_incorrect_defaulted_exception_spec) @@ -3801,11 +3967,28 @@ void Sema::CheckExplicitlyDefaultedCopyConstructor(CXXConstructorDecl *CD) { CtorType, CD->getLocation())) { HadError = true; } - } else if (First) { - // We set the declaration to have the computed exception spec here. - // We duplicate the one parameter type. + } + + // If a function is explicitly defaulted on its first declaration, + if (First) { + // -- it is implicitly considered to be constexpr if the implicit + // definition would be, + CD->setConstexpr(CD->getParent()->defaultedCopyConstructorIsConstexpr()); + + // -- it is implicitly considered to have the same + // exception-specification as if it had been implicitly declared, and + // + // FIXME: a compatible, but different, explicit exception specification + // will be silently overridden. We should issue a warning if this happens. EPI.ExtInfo = CtorType->getExtInfo(); + + // -- [...] it shall have the same parameter type as if it had been + // implicitly declared. CD->setType(Context.getFunctionType(Context.VoidTy, &ArgType, 1, EPI)); + + // Such a function is also trivial if the implicitly-declared function + // would have been. + CD->setTrivial(CD->getParent()->hasTrivialCopyConstructor()); } if (HadError) { @@ -3886,12 +4069,17 @@ void Sema::CheckExplicitlyDefaultedCopyAssignment(CXXMethodDecl *MD) { OperType, MD->getLocation())) { HadError = true; } - } else if (First) { + } + if (First) { // We set the declaration to have the computed exception spec here. // We duplicate the one parameter type. EPI.RefQualifier = OperType->getRefQualifier(); EPI.ExtInfo = OperType->getExtInfo(); MD->setType(Context.getFunctionType(ReturnType, &ArgType, 1, EPI)); + + // Such a function is also trivial if the implicitly-declared function + // would have been. + MD->setTrivial(MD->getParent()->hasTrivialCopyAssignment()); } if (HadError) { @@ -3899,7 +4087,7 @@ void Sema::CheckExplicitlyDefaultedCopyAssignment(CXXMethodDecl *MD) { return; } - if (ShouldDeleteCopyAssignmentOperator(MD)) { + if (ShouldDeleteSpecialMember(MD, CXXCopyAssignment)) { if (First) { MD->setDeletedAsWritten(); } else { @@ -3943,6 +4131,21 @@ void Sema::CheckExplicitlyDefaultedMoveConstructor(CXXConstructorDecl *CD) { HadError = true; } + // 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, + // Do not apply this rule to templates, since core issue 1358 makes such + // functions always instantiate to constexpr functions. + if (CD->isConstexpr() && + CD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) { + if (!CD->getParent()->defaultedMoveConstructorIsConstexpr()) { + Diag(CD->getLocStart(), diag::err_incorrect_defaulted_constexpr) + << CXXMoveConstructor; + HadError = true; + } + } + // and may have an explicit exception-specification only if it is compatible + // with the exception-specification on the implicit declaration. if (CtorType->hasExceptionSpec()) { if (CheckEquivalentExceptionSpec( PDiag(diag::err_incorrect_defaulted_exception_spec) @@ -3952,11 +4155,28 @@ void Sema::CheckExplicitlyDefaultedMoveConstructor(CXXConstructorDecl *CD) { CtorType, CD->getLocation())) { HadError = true; } - } else if (First) { - // We set the declaration to have the computed exception spec here. - // We duplicate the one parameter type. + } + + // If a function is explicitly defaulted on its first declaration, + if (First) { + // -- it is implicitly considered to be constexpr if the implicit + // definition would be, + CD->setConstexpr(CD->getParent()->defaultedMoveConstructorIsConstexpr()); + + // -- it is implicitly considered to have the same + // exception-specification as if it had been implicitly declared, and + // + // FIXME: a compatible, but different, explicit exception specification + // will be silently overridden. We should issue a warning if this happens. EPI.ExtInfo = CtorType->getExtInfo(); + + // -- [...] it shall have the same parameter type as if it had been + // implicitly declared. CD->setType(Context.getFunctionType(Context.VoidTy, &ArgType, 1, EPI)); + + // Such a function is also trivial if the implicitly-declared function + // would have been. + CD->setTrivial(CD->getParent()->hasTrivialMoveConstructor()); } if (HadError) { @@ -4035,12 +4255,17 @@ void Sema::CheckExplicitlyDefaultedMoveAssignment(CXXMethodDecl *MD) { OperType, MD->getLocation())) { HadError = true; } - } else if (First) { + } + if (First) { // We set the declaration to have the computed exception spec here. // We duplicate the one parameter type. EPI.RefQualifier = OperType->getRefQualifier(); EPI.ExtInfo = OperType->getExtInfo(); MD->setType(Context.getFunctionType(ReturnType, &ArgType, 1, EPI)); + + // Such a function is also trivial if the implicitly-declared function + // would have been. + MD->setTrivial(MD->getParent()->hasTrivialMoveAssignment()); } if (HadError) { @@ -4048,7 +4273,7 @@ void Sema::CheckExplicitlyDefaultedMoveAssignment(CXXMethodDecl *MD) { return; } - if (ShouldDeleteMoveAssignmentOperator(MD)) { + if (ShouldDeleteSpecialMember(MD, CXXMoveAssignment)) { if (First) { MD->setDeletedAsWritten(); } else { @@ -4082,14 +4307,19 @@ void Sema::CheckExplicitlyDefaultedDestructor(CXXDestructorDecl *DD) { DD->setInvalidDecl(); return; } - } else if (First) { + } + if (First) { // We set the declaration to have the computed exception spec here. // There are no parameters. EPI.ExtInfo = DtorType->getExtInfo(); DD->setType(Context.getFunctionType(Context.VoidTy, 0, 0, EPI)); + + // Such a function is also trivial if the implicitly-declared function + // would have been. + DD->setTrivial(DD->getParent()->hasTrivialDestructor()); } - if (ShouldDeleteDestructor(DD)) { + if (ShouldDeleteSpecialMember(DD, CXXDestructor)) { if (First) { DD->setDeletedAsWritten(); } else { @@ -4100,652 +4330,412 @@ void Sema::CheckExplicitlyDefaultedDestructor(CXXDestructorDecl *DD) { } } -/// This function implements the following C++0x paragraphs: -/// - [class.ctor]/5 -/// - [class.copy]/11 -bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM) { - assert(!MD->isInvalidDecl()); - CXXRecordDecl *RD = MD->getParent(); - assert(!RD->isDependentType() && "do deletion after instantiation"); - if (!LangOpts.CPlusPlus0x || RD->isInvalidDecl()) - return false; - - bool IsUnion = RD->isUnion(); - bool IsConstructor = false; - bool IsAssignment = false; - bool IsMove = false; - - bool ConstArg = false; +namespace { +struct SpecialMemberDeletionInfo { + Sema &S; + CXXMethodDecl *MD; + Sema::CXXSpecialMember CSM; + bool Diagnose; + + // Properties of the special member, computed for convenience. + bool IsConstructor, IsAssignment, IsMove, ConstArg, VolatileArg; + SourceLocation Loc; + + bool AllFieldsAreConst; + + SpecialMemberDeletionInfo(Sema &S, CXXMethodDecl *MD, + Sema::CXXSpecialMember CSM, bool Diagnose) + : S(S), MD(MD), CSM(CSM), Diagnose(Diagnose), + IsConstructor(false), IsAssignment(false), IsMove(false), + ConstArg(false), VolatileArg(false), Loc(MD->getLocation()), + AllFieldsAreConst(true) { + switch (CSM) { + case Sema::CXXDefaultConstructor: + case Sema::CXXCopyConstructor: + IsConstructor = true; + break; + case Sema::CXXMoveConstructor: + IsConstructor = true; + IsMove = true; + break; + case Sema::CXXCopyAssignment: + IsAssignment = true; + break; + case Sema::CXXMoveAssignment: + IsAssignment = true; + IsMove = true; + break; + case Sema::CXXDestructor: + break; + case Sema::CXXInvalid: + llvm_unreachable("invalid special member kind"); + } - switch (CSM) { - case CXXDefaultConstructor: - IsConstructor = true; - break; - case CXXCopyConstructor: - IsConstructor = true; - ConstArg = MD->getParamDecl(0)->getType().isConstQualified(); - break; - case CXXMoveConstructor: - IsConstructor = true; - IsMove = true; - break; - default: - llvm_unreachable("function only currently implemented for default ctors"); + if (MD->getNumParams()) { + ConstArg = MD->getParamDecl(0)->getType().isConstQualified(); + VolatileArg = MD->getParamDecl(0)->getType().isVolatileQualified(); + } } - SourceLocation Loc = MD->getLocation(); - - // Do access control from the special member function - ContextRAII MethodContext(*this, MD); - - bool AllConst = true; + bool inUnion() const { return MD->getParent()->isUnion(); } - // We do this because we should never actually use an anonymous - // union's constructor. - if (IsUnion && RD->isAnonymousStructOrUnion()) - return false; + /// Look up the corresponding special member in the given class. + Sema::SpecialMemberOverloadResult *lookupIn(CXXRecordDecl *Class) { + unsigned TQ = MD->getTypeQualifiers(); + return S.LookupSpecialMember(Class, CSM, ConstArg, VolatileArg, + MD->getRefQualifier() == RQ_RValue, + TQ & Qualifiers::Const, + TQ & Qualifiers::Volatile); + } - // FIXME: We should put some diagnostic logic right into this function. + typedef llvm::PointerUnion<CXXBaseSpecifier*, FieldDecl*> Subobject; - for (CXXRecordDecl::base_class_iterator BI = RD->bases_begin(), - BE = RD->bases_end(); - BI != BE; ++BI) { - // We'll handle this one later - if (BI->isVirtual()) - continue; + bool shouldDeleteForBase(CXXBaseSpecifier *Base); + bool shouldDeleteForField(FieldDecl *FD); + bool shouldDeleteForAllConstMembers(); - CXXRecordDecl *BaseDecl = BI->getType()->getAsCXXRecordDecl(); - assert(BaseDecl && "base isn't a CXXRecordDecl"); + bool shouldDeleteForClassSubobject(CXXRecordDecl *Class, Subobject Subobj); + bool shouldDeleteForSubobjectCall(Subobject Subobj, + Sema::SpecialMemberOverloadResult *SMOR, + bool IsDtorCallInCtor); - // Unless we have an assignment operator, the base's destructor must - // be accessible and not deleted. - if (!IsAssignment) { - CXXDestructorDecl *BaseDtor = LookupDestructor(BaseDecl); - if (BaseDtor->isDeleted()) - return true; - if (CheckDestructorAccess(Loc, BaseDtor, PDiag()) != - AR_accessible) - return true; - } + bool isAccessible(Subobject Subobj, CXXMethodDecl *D); +}; +} - // Finding the corresponding member in the base should lead to a - // unique, accessible, non-deleted function. If we are doing - // a destructor, we have already checked this case. - if (CSM != CXXDestructor) { - SpecialMemberOverloadResult *SMOR = - LookupSpecialMember(BaseDecl, CSM, ConstArg, false, false, false, - false); - if (!SMOR->hasSuccess()) - return true; - CXXMethodDecl *BaseMember = SMOR->getMethod(); - if (IsConstructor) { - CXXConstructorDecl *BaseCtor = cast<CXXConstructorDecl>(BaseMember); - if (CheckConstructorAccess(Loc, BaseCtor, BaseCtor->getAccess(), - PDiag()) != AR_accessible) - return true; +/// Is the given special member inaccessible when used on the given +/// sub-object. +bool SpecialMemberDeletionInfo::isAccessible(Subobject Subobj, + CXXMethodDecl *target) { + /// If we're operating on a base class, the object type is the + /// type of this special member. + QualType objectTy; + AccessSpecifier access = target->getAccess();; + if (CXXBaseSpecifier *base = Subobj.dyn_cast<CXXBaseSpecifier*>()) { + objectTy = S.Context.getTypeDeclType(MD->getParent()); + access = CXXRecordDecl::MergeAccess(base->getAccessSpecifier(), access); - // For a move operation, the corresponding operation must actually - // be a move operation (and not a copy selected by overload - // resolution) unless we are working on a trivially copyable class. - if (IsMove && !BaseCtor->isMoveConstructor() && - !BaseDecl->isTriviallyCopyable()) - return true; - } - } + // If we're operating on a field, the object type is the type of the field. + } else { + objectTy = S.Context.getTypeDeclType(target->getParent()); } - for (CXXRecordDecl::base_class_iterator BI = RD->vbases_begin(), - BE = RD->vbases_end(); - BI != BE; ++BI) { - CXXRecordDecl *BaseDecl = BI->getType()->getAsCXXRecordDecl(); - assert(BaseDecl && "base isn't a CXXRecordDecl"); - - // Unless we have an assignment operator, the base's destructor must - // be accessible and not deleted. - if (!IsAssignment) { - CXXDestructorDecl *BaseDtor = LookupDestructor(BaseDecl); - if (BaseDtor->isDeleted()) - return true; - if (CheckDestructorAccess(Loc, BaseDtor, PDiag()) != - AR_accessible) - return true; - } + return S.isSpecialMemberAccessibleForDeletion(target, access, objectTy); +} - // Finding the corresponding member in the base should lead to a - // unique, accessible, non-deleted function. - if (CSM != CXXDestructor) { - SpecialMemberOverloadResult *SMOR = - LookupSpecialMember(BaseDecl, CSM, ConstArg, false, false, false, - false); - if (!SMOR->hasSuccess()) - return true; - CXXMethodDecl *BaseMember = SMOR->getMethod(); - if (IsConstructor) { - CXXConstructorDecl *BaseCtor = cast<CXXConstructorDecl>(BaseMember); - if (CheckConstructorAccess(Loc, BaseCtor, BaseCtor->getAccess(), - PDiag()) != AR_accessible) - return true; +/// Check whether we should delete a special member due to the implicit +/// definition containing a call to a special member of a subobject. +bool SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall( + Subobject Subobj, Sema::SpecialMemberOverloadResult *SMOR, + bool IsDtorCallInCtor) { + CXXMethodDecl *Decl = SMOR->getMethod(); + FieldDecl *Field = Subobj.dyn_cast<FieldDecl*>(); - // For a move operation, the corresponding operation must actually - // be a move operation (and not a copy selected by overload - // resolution) unless we are working on a trivially copyable class. - if (IsMove && !BaseCtor->isMoveConstructor() && - !BaseDecl->isTriviallyCopyable()) - return true; - } - } - } + int DiagKind = -1; - for (CXXRecordDecl::field_iterator FI = RD->field_begin(), - FE = RD->field_end(); - FI != FE; ++FI) { - if (FI->isInvalidDecl() || FI->isUnnamedBitfield()) - continue; - - QualType FieldType = Context.getBaseElementType(FI->getType()); - CXXRecordDecl *FieldRecord = FieldType->getAsCXXRecordDecl(); + if (SMOR->getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted) + DiagKind = !Decl ? 0 : 1; + else if (SMOR->getKind() == Sema::SpecialMemberOverloadResult::Ambiguous) + DiagKind = 2; + else if (!isAccessible(Subobj, Decl)) + DiagKind = 3; + else if (!IsDtorCallInCtor && Field && Field->getParent()->isUnion() && + !Decl->isTrivial()) { + // A member of a union must have a trivial corresponding special member. + // As a weird special case, a destructor call from a union's constructor + // must be accessible and non-deleted, but need not be trivial. Such a + // destructor is never actually called, but is semantically checked as + // if it were. + DiagKind = 4; + } - // For a default constructor, all references must be initialized in-class - // and, if a union, it must have a non-const member. - if (CSM == CXXDefaultConstructor) { - if (FieldType->isReferenceType() && !FI->hasInClassInitializer()) - return true; + if (DiagKind == -1) + return false; - if (IsUnion && !FieldType.isConstQualified()) - AllConst = false; - // For a copy constructor, data members must not be of rvalue reference - // type. - } else if (CSM == CXXCopyConstructor) { - if (FieldType->isRValueReferenceType()) - return true; + if (Diagnose) { + if (Field) { + S.Diag(Field->getLocation(), + diag::note_deleted_special_member_class_subobject) + << CSM << MD->getParent() << /*IsField*/true + << Field << DiagKind << IsDtorCallInCtor; + } else { + CXXBaseSpecifier *Base = Subobj.get<CXXBaseSpecifier*>(); + S.Diag(Base->getLocStart(), + diag::note_deleted_special_member_class_subobject) + << CSM << MD->getParent() << /*IsField*/false + << Base->getType() << DiagKind << IsDtorCallInCtor; } - if (FieldRecord) { - // For a default constructor, a const member must have a user-provided - // default constructor or else be explicitly initialized. - if (CSM == CXXDefaultConstructor && FieldType.isConstQualified() && - !FI->hasInClassInitializer() && - !FieldRecord->hasUserProvidedDefaultConstructor()) - return true; - - // Some additional restrictions exist on the variant members. - if (!IsUnion && FieldRecord->isUnion() && - FieldRecord->isAnonymousStructOrUnion()) { - // We're okay to reuse AllConst here since we only care about the - // value otherwise if we're in a union. - AllConst = true; - - for (CXXRecordDecl::field_iterator UI = FieldRecord->field_begin(), - UE = FieldRecord->field_end(); - UI != UE; ++UI) { - QualType UnionFieldType = Context.getBaseElementType(UI->getType()); - CXXRecordDecl *UnionFieldRecord = - UnionFieldType->getAsCXXRecordDecl(); - - if (!UnionFieldType.isConstQualified()) - AllConst = false; - - if (UnionFieldRecord) { - // FIXME: Checking for accessibility and validity of this - // destructor is technically going beyond the - // standard, but this is believed to be a defect. - if (!IsAssignment) { - CXXDestructorDecl *FieldDtor = LookupDestructor(UnionFieldRecord); - if (FieldDtor->isDeleted()) - return true; - if (CheckDestructorAccess(Loc, FieldDtor, PDiag()) != - AR_accessible) - return true; - if (!FieldDtor->isTrivial()) - return true; - } - - if (CSM != CXXDestructor) { - SpecialMemberOverloadResult *SMOR = - LookupSpecialMember(UnionFieldRecord, CSM, ConstArg, false, - false, false, false); - // FIXME: Checking for accessibility and validity of this - // corresponding member is technically going beyond the - // standard, but this is believed to be a defect. - if (!SMOR->hasSuccess()) - return true; - - CXXMethodDecl *FieldMember = SMOR->getMethod(); - // A member of a union must have a trivial corresponding - // constructor. - if (!FieldMember->isTrivial()) - return true; - - if (IsConstructor) { - CXXConstructorDecl *FieldCtor = cast<CXXConstructorDecl>(FieldMember); - if (CheckConstructorAccess(Loc, FieldCtor, FieldCtor->getAccess(), - PDiag()) != AR_accessible) - return true; - } - } - } - } - - // At least one member in each anonymous union must be non-const - if (CSM == CXXDefaultConstructor && AllConst) - return true; - - // Don't try to initialize the anonymous union - // This is technically non-conformant, but sanity demands it. - continue; - } - - // Unless we're doing assignment, the field's destructor must be - // accessible and not deleted. - if (!IsAssignment) { - CXXDestructorDecl *FieldDtor = LookupDestructor(FieldRecord); - if (FieldDtor->isDeleted()) - return true; - if (CheckDestructorAccess(Loc, FieldDtor, PDiag()) != - AR_accessible) - return true; - } - - // Check that the corresponding member of the field is accessible, - // unique, and non-deleted. We don't do this if it has an explicit - // initialization when default-constructing. - if (CSM != CXXDestructor && - (CSM != CXXDefaultConstructor || !FI->hasInClassInitializer())) { - SpecialMemberOverloadResult *SMOR = - LookupSpecialMember(FieldRecord, CSM, ConstArg, false, false, false, - false); - if (!SMOR->hasSuccess()) - return true; + if (DiagKind == 1) + S.NoteDeletedFunction(Decl); + // FIXME: Explain inaccessibility if DiagKind == 3. + } - CXXMethodDecl *FieldMember = SMOR->getMethod(); - if (IsConstructor) { - CXXConstructorDecl *FieldCtor = cast<CXXConstructorDecl>(FieldMember); - if (CheckConstructorAccess(Loc, FieldCtor, FieldCtor->getAccess(), - PDiag()) != AR_accessible) - return true; + return true; +} - // For a move operation, the corresponding operation must actually - // be a move operation (and not a copy selected by overload - // resolution) unless we are working on a trivially copyable class. - if (IsMove && !FieldCtor->isMoveConstructor() && - !FieldRecord->isTriviallyCopyable()) - return true; - } +/// Check whether we should delete a special member function due to having a +/// direct or virtual base class or static data member of class type M. +bool SpecialMemberDeletionInfo::shouldDeleteForClassSubobject( + CXXRecordDecl *Class, Subobject Subobj) { + FieldDecl *Field = Subobj.dyn_cast<FieldDecl*>(); + + // C++11 [class.ctor]p5: + // -- any direct or virtual base class, or non-static data member with no + // brace-or-equal-initializer, has class type M (or array thereof) and + // either M has no default constructor or overload resolution as applied + // to M's default constructor results in an ambiguity or in a function + // that is deleted or inaccessible + // C++11 [class.copy]p11, C++11 [class.copy]p23: + // -- a direct or virtual base class B that cannot be copied/moved because + // overload resolution, as applied to B's corresponding special member, + // results in an ambiguity or a function that is deleted or inaccessible + // from the defaulted special member + // C++11 [class.dtor]p5: + // -- any direct or virtual base class [...] has a type with a destructor + // that is deleted or inaccessible + if (!(CSM == Sema::CXXDefaultConstructor && + Field && Field->hasInClassInitializer()) && + shouldDeleteForSubobjectCall(Subobj, lookupIn(Class), false)) + return true; - // We need the corresponding member of a union to be trivial so that - // we can safely copy them all simultaneously. - // FIXME: Note that performing the check here (where we rely on the lack - // of an in-class initializer) is technically ill-formed. However, this - // seems most obviously to be a bug in the standard. - if (IsUnion && !FieldMember->isTrivial()) - return true; - } - } else if (CSM == CXXDefaultConstructor && !IsUnion && - FieldType.isConstQualified() && !FI->hasInClassInitializer()) { - // We can't initialize a const member of non-class type to any value. + // C++11 [class.ctor]p5, C++11 [class.copy]p11: + // -- any direct or virtual base class or non-static data member has a + // type with a destructor that is deleted or inaccessible + if (IsConstructor) { + Sema::SpecialMemberOverloadResult *SMOR = + S.LookupSpecialMember(Class, Sema::CXXDestructor, + false, false, false, false, false); + if (shouldDeleteForSubobjectCall(Subobj, SMOR, true)) return true; - } } - // We can't have all const members in a union when default-constructing, - // or else they're all nonsensical garbage values that can't be changed. - if (CSM == CXXDefaultConstructor && IsUnion && AllConst) - return true; - return false; } -bool Sema::ShouldDeleteCopyAssignmentOperator(CXXMethodDecl *MD) { - CXXRecordDecl *RD = MD->getParent(); - assert(!RD->isDependentType() && "do deletion after instantiation"); - if (!LangOpts.CPlusPlus0x || RD->isInvalidDecl()) - return false; - - SourceLocation Loc = MD->getLocation(); - - // Do access control from the constructor - ContextRAII MethodContext(*this, MD); - - bool Union = RD->isUnion(); - - unsigned ArgQuals = - MD->getParamDecl(0)->getType()->getPointeeType().isConstQualified() ? - Qualifiers::Const : 0; - - // We do this because we should never actually use an anonymous - // union's constructor. - if (Union && RD->isAnonymousStructOrUnion()) - return false; - - // FIXME: We should put some diagnostic logic right into this function. - - // C++0x [class.copy]/20 - // A defaulted [copy] assignment operator for class X is defined as deleted - // if X has: +/// Check whether we should delete a special member function due to the class +/// having a particular direct or virtual base class. +bool SpecialMemberDeletionInfo::shouldDeleteForBase(CXXBaseSpecifier *Base) { + CXXRecordDecl *BaseClass = Base->getType()->getAsCXXRecordDecl(); + return shouldDeleteForClassSubobject(BaseClass, Base); +} - for (CXXRecordDecl::base_class_iterator BI = RD->bases_begin(), - BE = RD->bases_end(); - BI != BE; ++BI) { - // We'll handle this one later - if (BI->isVirtual()) - continue; +/// Check whether we should delete a special member function due to the class +/// having a particular non-static data member. +bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) { + QualType FieldType = S.Context.getBaseElementType(FD->getType()); + CXXRecordDecl *FieldRecord = FieldType->getAsCXXRecordDecl(); - QualType BaseType = BI->getType(); - CXXRecordDecl *BaseDecl = BaseType->getAsCXXRecordDecl(); - assert(BaseDecl && "base isn't a CXXRecordDecl"); - - // -- a [direct base class] B that cannot be [copied] because overload - // resolution, as applied to B's [copy] assignment operator, results in - // an ambiguity or a function that is deleted or inaccessible from the - // assignment operator - CXXMethodDecl *CopyOper = LookupCopyingAssignment(BaseDecl, ArgQuals, false, - 0); - if (!CopyOper || CopyOper->isDeleted()) + if (CSM == Sema::CXXDefaultConstructor) { + // For a default constructor, all references must be initialized in-class + // and, if a union, it must have a non-const member. + if (FieldType->isReferenceType() && !FD->hasInClassInitializer()) { + if (Diagnose) + S.Diag(FD->getLocation(), diag::note_deleted_default_ctor_uninit_field) + << MD->getParent() << FD << FieldType << /*Reference*/0; return true; - if (CheckDirectMemberAccess(Loc, CopyOper, PDiag()) != AR_accessible) + } + // C++11 [class.ctor]p5: any non-variant non-static data member of + // const-qualified type (or array thereof) with no + // brace-or-equal-initializer does not have a user-provided default + // constructor. + if (!inUnion() && FieldType.isConstQualified() && + !FD->hasInClassInitializer() && + (!FieldRecord || !FieldRecord->hasUserProvidedDefaultConstructor())) { + if (Diagnose) + S.Diag(FD->getLocation(), diag::note_deleted_default_ctor_uninit_field) + << MD->getParent() << FD << FieldType << /*Const*/1; return true; - } + } - for (CXXRecordDecl::base_class_iterator BI = RD->vbases_begin(), - BE = RD->vbases_end(); - BI != BE; ++BI) { - QualType BaseType = BI->getType(); - CXXRecordDecl *BaseDecl = BaseType->getAsCXXRecordDecl(); - assert(BaseDecl && "base isn't a CXXRecordDecl"); - - // -- a [virtual base class] B that cannot be [copied] because overload - // resolution, as applied to B's [copy] assignment operator, results in - // an ambiguity or a function that is deleted or inaccessible from the - // assignment operator - CXXMethodDecl *CopyOper = LookupCopyingAssignment(BaseDecl, ArgQuals, false, - 0); - if (!CopyOper || CopyOper->isDeleted()) + if (inUnion() && !FieldType.isConstQualified()) + AllFieldsAreConst = false; + } else if (CSM == Sema::CXXCopyConstructor) { + // For a copy constructor, data members must not be of rvalue reference + // type. + if (FieldType->isRValueReferenceType()) { + if (Diagnose) + S.Diag(FD->getLocation(), diag::note_deleted_copy_ctor_rvalue_reference) + << MD->getParent() << FD << FieldType; return true; - if (CheckDirectMemberAccess(Loc, CopyOper, PDiag()) != AR_accessible) + } + } else if (IsAssignment) { + // For an assignment operator, data members must not be of reference type. + if (FieldType->isReferenceType()) { + if (Diagnose) + S.Diag(FD->getLocation(), diag::note_deleted_assign_field) + << IsMove << MD->getParent() << FD << FieldType << /*Reference*/0; + return true; + } + if (!FieldRecord && FieldType.isConstQualified()) { + // C++11 [class.copy]p23: + // -- a non-static data member of const non-class type (or array thereof) + if (Diagnose) + S.Diag(FD->getLocation(), diag::note_deleted_assign_field) + << IsMove << MD->getParent() << FD << FieldType << /*Const*/1; return true; + } } - for (CXXRecordDecl::field_iterator FI = RD->field_begin(), - FE = RD->field_end(); - FI != FE; ++FI) { - if (FI->isUnnamedBitfield()) - continue; - - QualType FieldType = Context.getBaseElementType(FI->getType()); - - // -- a non-static data member of reference type - if (FieldType->isReferenceType()) - return true; + if (FieldRecord) { + // Some additional restrictions exist on the variant members. + if (!inUnion() && FieldRecord->isUnion() && + FieldRecord->isAnonymousStructOrUnion()) { + bool AllVariantFieldsAreConst = true; - // -- a non-static data member of const non-class type (or array thereof) - if (FieldType.isConstQualified() && !FieldType->isRecordType()) - return true; - - CXXRecordDecl *FieldRecord = FieldType->getAsCXXRecordDecl(); - - if (FieldRecord) { - // This is an anonymous union - if (FieldRecord->isUnion() && FieldRecord->isAnonymousStructOrUnion()) { - // Anonymous unions inside unions do not variant members create - if (!Union) { - for (CXXRecordDecl::field_iterator UI = FieldRecord->field_begin(), - UE = FieldRecord->field_end(); - UI != UE; ++UI) { - QualType UnionFieldType = Context.getBaseElementType(UI->getType()); - CXXRecordDecl *UnionFieldRecord = - UnionFieldType->getAsCXXRecordDecl(); - - // -- a variant member with a non-trivial [copy] assignment operator - // and X is a union-like class - if (UnionFieldRecord && - !UnionFieldRecord->hasTrivialCopyAssignment()) - return true; - } - } + // FIXME: Handle anonymous unions declared within anonymous unions. + for (CXXRecordDecl::field_iterator UI = FieldRecord->field_begin(), + UE = FieldRecord->field_end(); + UI != UE; ++UI) { + QualType UnionFieldType = S.Context.getBaseElementType(UI->getType()); - // Don't try to initalize an anonymous union - continue; - // -- a variant member with a non-trivial [copy] assignment operator - // and X is a union-like class - } else if (Union && !FieldRecord->hasTrivialCopyAssignment()) { + if (!UnionFieldType.isConstQualified()) + AllVariantFieldsAreConst = false; + + CXXRecordDecl *UnionFieldRecord = UnionFieldType->getAsCXXRecordDecl(); + if (UnionFieldRecord && + shouldDeleteForClassSubobject(UnionFieldRecord, *UI)) return true; } - CXXMethodDecl *CopyOper = LookupCopyingAssignment(FieldRecord, ArgQuals, - false, 0); - if (!CopyOper || CopyOper->isDeleted()) - return true; - if (CheckDirectMemberAccess(Loc, CopyOper, PDiag()) != AR_accessible) + // At least one member in each anonymous union must be non-const + if (CSM == Sema::CXXDefaultConstructor && AllVariantFieldsAreConst && + FieldRecord->field_begin() != FieldRecord->field_end()) { + if (Diagnose) + S.Diag(FieldRecord->getLocation(), + diag::note_deleted_default_ctor_all_const) + << MD->getParent() << /*anonymous union*/1; return true; + } + + // Don't check the implicit member of the anonymous union type. + // This is technically non-conformant, but sanity demands it. + return false; } + + if (shouldDeleteForClassSubobject(FieldRecord, FD)) + return true; } return false; } -bool Sema::ShouldDeleteMoveAssignmentOperator(CXXMethodDecl *MD) { +/// C++11 [class.ctor] p5: +/// A defaulted default constructor for a class X is defined as deleted if +/// X is a union and all of its variant members are of const-qualified type. +bool SpecialMemberDeletionInfo::shouldDeleteForAllConstMembers() { + // This is a silly definition, because it gives an empty union a deleted + // default constructor. Don't do that. + if (CSM == Sema::CXXDefaultConstructor && inUnion() && AllFieldsAreConst && + (MD->getParent()->field_begin() != MD->getParent()->field_end())) { + if (Diagnose) + S.Diag(MD->getParent()->getLocation(), + diag::note_deleted_default_ctor_all_const) + << MD->getParent() << /*not anonymous union*/0; + return true; + } + return false; +} + +/// Determine whether a defaulted special member function should be defined as +/// deleted, as specified in C++11 [class.ctor]p5, C++11 [class.copy]p11, +/// C++11 [class.copy]p23, and C++11 [class.dtor]p5. +bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, + bool Diagnose) { + assert(!MD->isInvalidDecl()); CXXRecordDecl *RD = MD->getParent(); assert(!RD->isDependentType() && "do deletion after instantiation"); if (!LangOpts.CPlusPlus0x || RD->isInvalidDecl()) return false; - SourceLocation Loc = MD->getLocation(); - - // Do access control from the constructor - ContextRAII MethodContext(*this, MD); - - bool Union = RD->isUnion(); - - // We do this because we should never actually use an anonymous - // union's constructor. - if (Union && RD->isAnonymousStructOrUnion()) - return false; - - // C++0x [class.copy]/20 - // A defaulted [move] assignment operator for class X is defined as deleted - // if X has: - - // -- for the move constructor, [...] any direct or indirect virtual base - // class. - if (RD->getNumVBases() != 0) + // C++11 [expr.lambda.prim]p19: + // The closure type associated with a lambda-expression has a + // deleted (8.4.3) default constructor and a deleted copy + // assignment operator. + if (RD->isLambda() && + (CSM == CXXDefaultConstructor || CSM == CXXCopyAssignment)) { + if (Diagnose) + Diag(RD->getLocation(), diag::note_lambda_decl); return true; + } - for (CXXRecordDecl::base_class_iterator BI = RD->bases_begin(), - BE = RD->bases_end(); - BI != BE; ++BI) { - - QualType BaseType = BI->getType(); - CXXRecordDecl *BaseDecl = BaseType->getAsCXXRecordDecl(); - assert(BaseDecl && "base isn't a CXXRecordDecl"); - - // -- a [direct base class] B that cannot be [moved] because overload - // resolution, as applied to B's [move] assignment operator, results in - // an ambiguity or a function that is deleted or inaccessible from the - // assignment operator - CXXMethodDecl *MoveOper = LookupMovingAssignment(BaseDecl, false, 0); - if (!MoveOper || MoveOper->isDeleted()) - return true; - if (CheckDirectMemberAccess(Loc, MoveOper, PDiag()) != AR_accessible) - return true; + // For an anonymous struct or union, the copy and assignment special members + // will never be used, so skip the check. For an anonymous union declared at + // namespace scope, the constructor and destructor are used. + if (CSM != CXXDefaultConstructor && CSM != CXXDestructor && + RD->isAnonymousStructOrUnion()) + return false; - // -- for the move assignment operator, a [direct base class] with a type - // that does not have a move assignment operator and is not trivially - // copyable. - if (!MoveOper->isMoveAssignmentOperator() && - !BaseDecl->isTriviallyCopyable()) + // C++11 [class.copy]p7, p18: + // If the class definition declares a move constructor or move assignment + // operator, an implicitly declared copy constructor or copy assignment + // operator is defined as deleted. + if (MD->isImplicit() && + (CSM == CXXCopyConstructor || CSM == CXXCopyAssignment)) { + CXXMethodDecl *UserDeclaredMove = 0; + + // In Microsoft mode, a user-declared move only causes the deletion of the + // corresponding copy operation, not both copy operations. + if (RD->hasUserDeclaredMoveConstructor() && + (!getLangOpts().MicrosoftMode || CSM == CXXCopyConstructor)) { + if (!Diagnose) return true; + UserDeclaredMove = RD->getMoveConstructor(); + assert(UserDeclaredMove); + } else if (RD->hasUserDeclaredMoveAssignment() && + (!getLangOpts().MicrosoftMode || CSM == CXXCopyAssignment)) { + if (!Diagnose) return true; + UserDeclaredMove = RD->getMoveAssignmentOperator(); + assert(UserDeclaredMove); + } + + if (UserDeclaredMove) { + Diag(UserDeclaredMove->getLocation(), + diag::note_deleted_copy_user_declared_move) + << (CSM == CXXCopyAssignment) << RD + << UserDeclaredMove->isMoveAssignmentOperator(); return true; + } } - for (CXXRecordDecl::field_iterator FI = RD->field_begin(), - FE = RD->field_end(); - FI != FE; ++FI) { - if (FI->isUnnamedBitfield()) - continue; - - QualType FieldType = Context.getBaseElementType(FI->getType()); - - // -- a non-static data member of reference type - if (FieldType->isReferenceType()) - return true; + // Do access control from the special member function + ContextRAII MethodContext(*this, MD); - // -- a non-static data member of const non-class type (or array thereof) - if (FieldType.isConstQualified() && !FieldType->isRecordType()) + // C++11 [class.dtor]p5: + // -- for a virtual destructor, lookup of the non-array deallocation function + // results in an ambiguity or in a function that is deleted or inaccessible + if (CSM == CXXDestructor && MD->isVirtual()) { + FunctionDecl *OperatorDelete = 0; + DeclarationName Name = + Context.DeclarationNames.getCXXOperatorName(OO_Delete); + if (FindDeallocationFunction(MD->getLocation(), MD->getParent(), Name, + OperatorDelete, false)) { + if (Diagnose) + Diag(RD->getLocation(), diag::note_deleted_dtor_no_operator_delete); return true; - - CXXRecordDecl *FieldRecord = FieldType->getAsCXXRecordDecl(); - - if (FieldRecord) { - // This is an anonymous union - if (FieldRecord->isUnion() && FieldRecord->isAnonymousStructOrUnion()) { - // Anonymous unions inside unions do not variant members create - if (!Union) { - for (CXXRecordDecl::field_iterator UI = FieldRecord->field_begin(), - UE = FieldRecord->field_end(); - UI != UE; ++UI) { - QualType UnionFieldType = Context.getBaseElementType(UI->getType()); - CXXRecordDecl *UnionFieldRecord = - UnionFieldType->getAsCXXRecordDecl(); - - // -- a variant member with a non-trivial [move] assignment operator - // and X is a union-like class - if (UnionFieldRecord && - !UnionFieldRecord->hasTrivialMoveAssignment()) - return true; - } - } - - // Don't try to initalize an anonymous union - continue; - // -- a variant member with a non-trivial [move] assignment operator - // and X is a union-like class - } else if (Union && !FieldRecord->hasTrivialMoveAssignment()) { - return true; - } - - CXXMethodDecl *MoveOper = LookupMovingAssignment(FieldRecord, false, 0); - if (!MoveOper || MoveOper->isDeleted()) - return true; - if (CheckDirectMemberAccess(Loc, MoveOper, PDiag()) != AR_accessible) - return true; - - // -- for the move assignment operator, a [non-static data member] with a - // type that does not have a move assignment operator and is not - // trivially copyable. - if (!MoveOper->isMoveAssignmentOperator() && - !FieldRecord->isTriviallyCopyable()) - return true; } } - return false; -} - -bool Sema::ShouldDeleteDestructor(CXXDestructorDecl *DD) { - CXXRecordDecl *RD = DD->getParent(); - assert(!RD->isDependentType() && "do deletion after instantiation"); - if (!LangOpts.CPlusPlus0x || RD->isInvalidDecl()) - return false; - - SourceLocation Loc = DD->getLocation(); - - // Do access control from the destructor - ContextRAII CtorContext(*this, DD); - - bool Union = RD->isUnion(); - - // We do this because we should never actually use an anonymous - // union's destructor. - if (Union && RD->isAnonymousStructOrUnion()) - return false; + SpecialMemberDeletionInfo SMI(*this, MD, CSM, Diagnose); - // C++0x [class.dtor]p5 - // A defaulted destructor for a class X is defined as deleted if: for (CXXRecordDecl::base_class_iterator BI = RD->bases_begin(), - BE = RD->bases_end(); - BI != BE; ++BI) { - // We'll handle this one later - if (BI->isVirtual()) - continue; - - CXXRecordDecl *BaseDecl = BI->getType()->getAsCXXRecordDecl(); - CXXDestructorDecl *BaseDtor = LookupDestructor(BaseDecl); - assert(BaseDtor && "base has no destructor"); - - // -- any direct or virtual base class has a deleted destructor or - // a destructor that is inaccessible from the defaulted destructor - if (BaseDtor->isDeleted()) + BE = RD->bases_end(); BI != BE; ++BI) + if (!BI->isVirtual() && + SMI.shouldDeleteForBase(BI)) return true; - if (CheckDestructorAccess(Loc, BaseDtor, PDiag()) != - AR_accessible) - return true; - } for (CXXRecordDecl::base_class_iterator BI = RD->vbases_begin(), - BE = RD->vbases_end(); - BI != BE; ++BI) { - CXXRecordDecl *BaseDecl = BI->getType()->getAsCXXRecordDecl(); - CXXDestructorDecl *BaseDtor = LookupDestructor(BaseDecl); - assert(BaseDtor && "base has no destructor"); - - // -- any direct or virtual base class has a deleted destructor or - // a destructor that is inaccessible from the defaulted destructor - if (BaseDtor->isDeleted()) - return true; - if (CheckDestructorAccess(Loc, BaseDtor, PDiag()) != - AR_accessible) + BE = RD->vbases_end(); BI != BE; ++BI) + if (SMI.shouldDeleteForBase(BI)) return true; - } for (CXXRecordDecl::field_iterator FI = RD->field_begin(), - FE = RD->field_end(); - FI != FE; ++FI) { - QualType FieldType = Context.getBaseElementType(FI->getType()); - CXXRecordDecl *FieldRecord = FieldType->getAsCXXRecordDecl(); - if (FieldRecord) { - if (FieldRecord->isUnion() && FieldRecord->isAnonymousStructOrUnion()) { - for (CXXRecordDecl::field_iterator UI = FieldRecord->field_begin(), - UE = FieldRecord->field_end(); - UI != UE; ++UI) { - QualType UnionFieldType = Context.getBaseElementType(FI->getType()); - CXXRecordDecl *UnionFieldRecord = - UnionFieldType->getAsCXXRecordDecl(); - - // -- X is a union-like class that has a variant member with a non- - // trivial destructor. - if (UnionFieldRecord && !UnionFieldRecord->hasTrivialDestructor()) - return true; - } - // Technically we are supposed to do this next check unconditionally. - // But that makes absolutely no sense. - } else { - CXXDestructorDecl *FieldDtor = LookupDestructor(FieldRecord); - - // -- any of the non-static data members has class type M (or array - // thereof) and M has a deleted destructor or a destructor that is - // inaccessible from the defaulted destructor - if (FieldDtor->isDeleted()) - return true; - if (CheckDestructorAccess(Loc, FieldDtor, PDiag()) != - AR_accessible) - return true; - - // -- X is a union-like class that has a variant member with a non- - // trivial destructor. - if (Union && !FieldDtor->isTrivial()) - return true; - } - } - } - - if (DD->isVirtual()) { - FunctionDecl *OperatorDelete = 0; - DeclarationName Name = - Context.DeclarationNames.getCXXOperatorName(OO_Delete); - if (FindDeallocationFunction(Loc, RD, Name, OperatorDelete, - false)) + FE = RD->field_end(); FI != FE; ++FI) + if (!FI->isInvalidDecl() && !FI->isUnnamedBitfield() && + SMI.shouldDeleteForField(*FI)) return true; - } + if (SMI.shouldDeleteForAllConstMembers()) + return true; return false; } @@ -4876,6 +4866,9 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { if (!ClassDecl->hasUserDeclaredCopyConstructor()) ++ASTContext::NumImplicitCopyConstructors; + if (getLangOpts().CPlusPlus0x && ClassDecl->needsImplicitMoveConstructor()) + ++ASTContext::NumImplicitMoveConstructors; + if (!ClassDecl->hasUserDeclaredCopyAssignment()) { ++ASTContext::NumImplicitCopyAssignmentOperators; @@ -4887,6 +4880,14 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { DeclareImplicitCopyAssignment(ClassDecl); } + if (getLangOpts().CPlusPlus0x && ClassDecl->needsImplicitMoveAssignment()) { + ++ASTContext::NumImplicitMoveAssignmentOperators; + + // Likewise for the move assignment operator. + if (ClassDecl->isDynamicClass()) + DeclareImplicitMoveAssignment(ClassDecl); + } + if (!ClassDecl->hasUserDeclaredDestructor()) { ++ASTContext::NumImplicitDestructors; @@ -5139,7 +5140,7 @@ bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) { if (FindDeallocationFunction(Loc, RD, Name, OperatorDelete)) return true; - MarkDeclarationReferenced(Loc, OperatorDelete); + MarkFunctionReferenced(Loc, OperatorDelete); Destructor->setOperatorDelete(OperatorDelete); } @@ -5342,9 +5343,11 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R, R = Context.getFunctionType(ConvType, 0, 0, Proto->getExtProtoInfo()); // C++0x explicit conversion operators. - if (D.getDeclSpec().isExplicitSpecified() && !getLangOptions().CPlusPlus0x) + if (D.getDeclSpec().isExplicitSpecified()) Diag(D.getDeclSpec().getExplicitSpecLoc(), - diag::warn_explicit_conversion_functions) + getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_explicit_conversion_functions : + diag::ext_explicit_conversion_functions) << SourceRange(D.getDeclSpec().getExplicitSpecLoc()); } @@ -5413,17 +5416,13 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, SourceLocation StartLoc = InlineLoc.isValid() ? InlineLoc : NamespaceLoc; // For anonymous namespace, take the location of the left brace. SourceLocation Loc = II ? IdentLoc : LBrace; - NamespaceDecl *Namespc = NamespaceDecl::Create(Context, CurContext, - StartLoc, Loc, II); - Namespc->setInline(InlineLoc.isValid()); - + bool IsInline = InlineLoc.isValid(); + bool IsInvalid = false; + bool IsStd = false; + bool AddToKnown = false; Scope *DeclRegionScope = NamespcScope->getParent(); - ProcessDeclAttributeList(DeclRegionScope, Namespc, AttrList); - - if (const VisibilityAttr *Attr = Namespc->getAttr<VisibilityAttr>()) - PushNamespaceVisibilityAttr(Attr); - + NamespaceDecl *PrevNS = 0; if (II) { // C++ [namespace.def]p2: // The identifier in an original-namespace-definition shall not @@ -5437,11 +5436,11 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, // look through using directives, just look for any ordinary names. const unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Member | - Decl::IDNS_Type | Decl::IDNS_Using | Decl::IDNS_Tag | - Decl::IDNS_Namespace; + Decl::IDNS_Type | Decl::IDNS_Using | Decl::IDNS_Tag | + Decl::IDNS_Namespace; NamedDecl *PrevDecl = 0; for (DeclContext::lookup_result R - = CurContext->getRedeclContext()->lookup(II); + = CurContext->getRedeclContext()->lookup(II); R.first != R.second; ++R.first) { if ((*R.first)->getIdentifierNamespace() & IDNS) { PrevDecl = *R.first; @@ -5449,100 +5448,91 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, } } - if (NamespaceDecl *OrigNS = dyn_cast_or_null<NamespaceDecl>(PrevDecl)) { + PrevNS = dyn_cast_or_null<NamespaceDecl>(PrevDecl); + + if (PrevNS) { // This is an extended namespace definition. - if (Namespc->isInline() != OrigNS->isInline()) { + if (IsInline != PrevNS->isInline()) { // inline-ness must match - if (OrigNS->isInline()) { + if (PrevNS->isInline()) { // The user probably just forgot the 'inline', so suggest that it // be added back. - Diag(Namespc->getLocation(), - diag::warn_inline_namespace_reopened_noninline) + Diag(Loc, diag::warn_inline_namespace_reopened_noninline) << FixItHint::CreateInsertion(NamespaceLoc, "inline "); } else { - Diag(Namespc->getLocation(), diag::err_inline_namespace_mismatch) - << Namespc->isInline(); + Diag(Loc, diag::err_inline_namespace_mismatch) + << IsInline; } - Diag(OrigNS->getLocation(), diag::note_previous_definition); - - // Recover by ignoring the new namespace's inline status. - Namespc->setInline(OrigNS->isInline()); - } - - // Attach this namespace decl to the chain of extended namespace - // definitions. - OrigNS->setNextNamespace(Namespc); - Namespc->setOriginalNamespace(OrigNS->getOriginalNamespace()); - - // Remove the previous declaration from the scope. - if (DeclRegionScope->isDeclScope(OrigNS)) { - IdResolver.RemoveDecl(OrigNS); - DeclRegionScope->RemoveDecl(OrigNS); - } + Diag(PrevNS->getLocation(), diag::note_previous_definition); + + IsInline = PrevNS->isInline(); + } } else if (PrevDecl) { // This is an invalid name redefinition. - Diag(Namespc->getLocation(), diag::err_redefinition_different_kind) - << Namespc->getDeclName(); + Diag(Loc, diag::err_redefinition_different_kind) + << II; Diag(PrevDecl->getLocation(), diag::note_previous_definition); - Namespc->setInvalidDecl(); + IsInvalid = true; // Continue on to push Namespc as current DeclContext and return it. - } else if (II->isStr("std") && + } else if (II->isStr("std") && CurContext->getRedeclContext()->isTranslationUnit()) { // This is the first "real" definition of the namespace "std", so update // our cache of the "std" namespace to point at this definition. - if (NamespaceDecl *StdNS = getStdNamespace()) { - // We had already defined a dummy namespace "std". Link this new - // namespace definition to the dummy namespace "std". - StdNS->setNextNamespace(Namespc); - StdNS->setLocation(IdentLoc); - Namespc->setOriginalNamespace(StdNS->getOriginalNamespace()); - } - - // Make our StdNamespace cache point at the first real definition of the - // "std" namespace. - StdNamespace = Namespc; - - // Add this instance of "std" to the set of known namespaces - KnownNamespaces[Namespc] = false; - } else if (!Namespc->isInline()) { - // Since this is an "original" namespace, add it to the known set of - // namespaces if it is not an inline namespace. - KnownNamespaces[Namespc] = false; + PrevNS = getStdNamespace(); + IsStd = true; + AddToKnown = !IsInline; + } else { + // We've seen this namespace for the first time. + AddToKnown = !IsInline; } - - PushOnScopeChains(Namespc, DeclRegionScope); } else { // Anonymous namespaces. - assert(Namespc->isAnonymousNamespace()); - - // Link the anonymous namespace into its parent. - NamespaceDecl *PrevDecl; + + // Determine whether the parent already has an anonymous namespace. DeclContext *Parent = CurContext->getRedeclContext(); if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(Parent)) { - PrevDecl = TU->getAnonymousNamespace(); - TU->setAnonymousNamespace(Namespc); + PrevNS = TU->getAnonymousNamespace(); } else { NamespaceDecl *ND = cast<NamespaceDecl>(Parent); - PrevDecl = ND->getAnonymousNamespace(); - ND->setAnonymousNamespace(Namespc); + PrevNS = ND->getAnonymousNamespace(); } - // Link the anonymous namespace with its previous declaration. - if (PrevDecl) { - assert(PrevDecl->isAnonymousNamespace()); - assert(!PrevDecl->getNextNamespace()); - Namespc->setOriginalNamespace(PrevDecl->getOriginalNamespace()); - PrevDecl->setNextNamespace(Namespc); + if (PrevNS && IsInline != PrevNS->isInline()) { + // inline-ness must match + Diag(Loc, diag::err_inline_namespace_mismatch) + << IsInline; + Diag(PrevNS->getLocation(), diag::note_previous_definition); + + // Recover by ignoring the new namespace's inline status. + IsInline = PrevNS->isInline(); + } + } + + NamespaceDecl *Namespc = NamespaceDecl::Create(Context, CurContext, IsInline, + StartLoc, Loc, II, PrevNS); + if (IsInvalid) + Namespc->setInvalidDecl(); + + ProcessDeclAttributeList(DeclRegionScope, Namespc, AttrList); - if (Namespc->isInline() != PrevDecl->isInline()) { - // inline-ness must match - Diag(Namespc->getLocation(), diag::err_inline_namespace_mismatch) - << Namespc->isInline(); - Diag(PrevDecl->getLocation(), diag::note_previous_definition); - Namespc->setInvalidDecl(); - // Recover by ignoring the new namespace's inline status. - Namespc->setInline(PrevDecl->isInline()); - } + // FIXME: Should we be merging attributes? + if (const VisibilityAttr *Attr = Namespc->getAttr<VisibilityAttr>()) + PushNamespaceVisibilityAttr(Attr, Loc); + + if (IsStd) + StdNamespace = Namespc; + if (AddToKnown) + KnownNamespaces[Namespc] = false; + + if (II) { + PushOnScopeChains(Namespc, DeclRegionScope); + } else { + // Link the anonymous namespace into its parent. + DeclContext *Parent = CurContext->getRedeclContext(); + if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(Parent)) { + TU->setAnonymousNamespace(Namespc); + } else { + cast<NamespaceDecl>(Parent)->setAnonymousNamespace(Namespc); } CurContext->addDecl(Namespc); @@ -5563,7 +5553,7 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, // declarations semantically contained within an anonymous // namespace internal linkage. - if (!PrevDecl) { + if (!PrevNS) { UsingDirectiveDecl* UD = UsingDirectiveDecl::Create(Context, CurContext, /* 'using' */ LBrace, @@ -5602,7 +5592,7 @@ void Sema::ActOnFinishNamespaceDef(Decl *Dcl, SourceLocation RBrace) { Namespc->setRBraceLoc(RBrace); PopDeclContext(); if (Namespc->hasAttr<VisibilityAttr>()) - PopPragmaVisibility(); + PopPragmaVisibility(true, RBrace); } CXXRecordDecl *Sema::getStdBadAlloc() const { @@ -5622,14 +5612,142 @@ NamespaceDecl *Sema::getOrCreateStdNamespace() { // The "std" namespace has not yet been defined, so build one implicitly. StdNamespace = NamespaceDecl::Create(Context, Context.getTranslationUnitDecl(), + /*Inline=*/false, SourceLocation(), SourceLocation(), - &PP.getIdentifierTable().get("std")); + &PP.getIdentifierTable().get("std"), + /*PrevDecl=*/0); getStdNamespace()->setImplicit(true); } return getStdNamespace(); } +bool Sema::isStdInitializerList(QualType Ty, QualType *Element) { + assert(getLangOpts().CPlusPlus && + "Looking for std::initializer_list outside of C++."); + + // We're looking for implicit instantiations of + // template <typename E> class std::initializer_list. + + if (!StdNamespace) // If we haven't seen namespace std yet, this can't be it. + return false; + + ClassTemplateDecl *Template = 0; + const TemplateArgument *Arguments = 0; + + if (const RecordType *RT = Ty->getAs<RecordType>()) { + + ClassTemplateSpecializationDecl *Specialization = + dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl()); + if (!Specialization) + return false; + + Template = Specialization->getSpecializedTemplate(); + Arguments = Specialization->getTemplateArgs().data(); + } else if (const TemplateSpecializationType *TST = + Ty->getAs<TemplateSpecializationType>()) { + Template = dyn_cast_or_null<ClassTemplateDecl>( + TST->getTemplateName().getAsTemplateDecl()); + Arguments = TST->getArgs(); + } + if (!Template) + return false; + + if (!StdInitializerList) { + // Haven't recognized std::initializer_list yet, maybe this is it. + CXXRecordDecl *TemplateClass = Template->getTemplatedDecl(); + if (TemplateClass->getIdentifier() != + &PP.getIdentifierTable().get("initializer_list") || + !getStdNamespace()->InEnclosingNamespaceSetOf( + TemplateClass->getDeclContext())) + return false; + // This is a template called std::initializer_list, but is it the right + // template? + TemplateParameterList *Params = Template->getTemplateParameters(); + if (Params->getMinRequiredArguments() != 1) + return false; + if (!isa<TemplateTypeParmDecl>(Params->getParam(0))) + return false; + + // It's the right template. + StdInitializerList = Template; + } + + if (Template != StdInitializerList) + return false; + + // This is an instance of std::initializer_list. Find the argument type. + if (Element) + *Element = Arguments[0].getAsType(); + return true; +} + +static ClassTemplateDecl *LookupStdInitializerList(Sema &S, SourceLocation Loc){ + NamespaceDecl *Std = S.getStdNamespace(); + if (!Std) { + S.Diag(Loc, diag::err_implied_std_initializer_list_not_found); + return 0; + } + + LookupResult Result(S, &S.PP.getIdentifierTable().get("initializer_list"), + Loc, Sema::LookupOrdinaryName); + if (!S.LookupQualifiedName(Result, Std)) { + S.Diag(Loc, diag::err_implied_std_initializer_list_not_found); + return 0; + } + ClassTemplateDecl *Template = Result.getAsSingle<ClassTemplateDecl>(); + if (!Template) { + Result.suppressDiagnostics(); + // We found something weird. Complain about the first thing we found. + NamedDecl *Found = *Result.begin(); + S.Diag(Found->getLocation(), diag::err_malformed_std_initializer_list); + return 0; + } + + // We found some template called std::initializer_list. Now verify that it's + // correct. + TemplateParameterList *Params = Template->getTemplateParameters(); + if (Params->getMinRequiredArguments() != 1 || + !isa<TemplateTypeParmDecl>(Params->getParam(0))) { + S.Diag(Template->getLocation(), diag::err_malformed_std_initializer_list); + return 0; + } + + return Template; +} + +QualType Sema::BuildStdInitializerList(QualType Element, SourceLocation Loc) { + if (!StdInitializerList) { + StdInitializerList = LookupStdInitializerList(*this, Loc); + if (!StdInitializerList) + return QualType(); + } + + TemplateArgumentListInfo Args(Loc, Loc); + Args.addArgument(TemplateArgumentLoc(TemplateArgument(Element), + Context.getTrivialTypeSourceInfo(Element, + Loc))); + return Context.getCanonicalType( + CheckTemplateIdType(TemplateName(StdInitializerList), Loc, Args)); +} + +bool Sema::isInitListConstructor(const CXXConstructorDecl* Ctor) { + // C++ [dcl.init.list]p2: + // A constructor is an initializer-list constructor if its first parameter + // is of type std::initializer_list<E> or reference to possibly cv-qualified + // std::initializer_list<E> for some type E, and either there are no other + // parameters or else all other parameters have default arguments. + if (Ctor->getNumParams() < 1 || + (Ctor->getNumParams() > 1 && !Ctor->getParamDecl(1)->hasDefaultArg())) + return false; + + QualType ArgType = Ctor->getParamDecl(0)->getType(); + if (const ReferenceType *RT = ArgType->getAs<ReferenceType>()) + ArgType = RT->getPointeeType().getUnqualifiedType(); + + return isStdInitializerList(ArgType, 0); +} + /// \brief Determine whether a using statement is in a context where it will be /// apply in all contexts. static bool IsUsingDirectiveInToplevelContext(DeclContext *CurContext) { @@ -5643,35 +5761,46 @@ static bool IsUsingDirectiveInToplevelContext(DeclContext *CurContext) { } } +namespace { + +// Callback to only accept typo corrections that are namespaces. +class NamespaceValidatorCCC : public CorrectionCandidateCallback { + public: + virtual bool ValidateCandidate(const TypoCorrection &candidate) { + if (NamedDecl *ND = candidate.getCorrectionDecl()) { + return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND); + } + return false; + } +}; + +} + static bool TryNamespaceTypoCorrection(Sema &S, LookupResult &R, Scope *Sc, CXXScopeSpec &SS, SourceLocation IdentLoc, IdentifierInfo *Ident) { + NamespaceValidatorCCC Validator; R.clear(); if (TypoCorrection Corrected = S.CorrectTypo(R.getLookupNameInfo(), - R.getLookupKind(), Sc, &SS, NULL, - false, S.CTC_NoKeywords, NULL)) { - if (Corrected.getCorrectionDeclAs<NamespaceDecl>() || - Corrected.getCorrectionDeclAs<NamespaceAliasDecl>()) { - std::string CorrectedStr(Corrected.getAsString(S.getLangOptions())); - std::string CorrectedQuotedStr(Corrected.getQuoted(S.getLangOptions())); - if (DeclContext *DC = S.computeDeclContext(SS, false)) - S.Diag(IdentLoc, diag::err_using_directive_member_suggest) - << Ident << DC << CorrectedQuotedStr << SS.getRange() - << FixItHint::CreateReplacement(IdentLoc, CorrectedStr); - else - S.Diag(IdentLoc, diag::err_using_directive_suggest) - << Ident << CorrectedQuotedStr - << FixItHint::CreateReplacement(IdentLoc, CorrectedStr); + R.getLookupKind(), Sc, &SS, + Validator)) { + std::string CorrectedStr(Corrected.getAsString(S.getLangOpts())); + std::string CorrectedQuotedStr(Corrected.getQuoted(S.getLangOpts())); + if (DeclContext *DC = S.computeDeclContext(SS, false)) + S.Diag(IdentLoc, diag::err_using_directive_member_suggest) + << Ident << DC << CorrectedQuotedStr << SS.getRange() + << FixItHint::CreateReplacement(IdentLoc, CorrectedStr); + else + S.Diag(IdentLoc, diag::err_using_directive_suggest) + << Ident << CorrectedQuotedStr + << FixItHint::CreateReplacement(IdentLoc, CorrectedStr); - S.Diag(Corrected.getCorrectionDecl()->getLocation(), - diag::note_namespace_defined_here) << CorrectedQuotedStr; + S.Diag(Corrected.getCorrectionDecl()->getLocation(), + diag::note_namespace_defined_here) << CorrectedQuotedStr; - Ident = Corrected.getCorrectionAsIdentifierInfo(); - R.addDecl(Corrected.getCorrectionDecl()); - return true; - } - R.setLookupName(Ident); + R.addDecl(Corrected.getCorrectionDecl()); + return true; } return false; } @@ -5757,14 +5886,15 @@ Decl *Sema::ActOnUsingDirective(Scope *S, } void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) { - // If scope has associated entity, then using directive is at namespace - // or translation unit scope. We add UsingDirectiveDecls, into - // it's lookup structure. - if (DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity())) + // If the scope has an associated entity and the using directive is at + // namespace or translation unit scope, add the UsingDirectiveDecl into + // its lookup structure so qualified name lookup can find it. + DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity()); + if (Ctx && !Ctx->isFunctionOrMethod()) Ctx->addDecl(UDir); else - // Otherwise it is block-sope. using-directives will affect lookup - // only to the end of scope. + // Otherwise, it is at block sope. The using-directives will affect lookup + // only to the end of the scope. S->PushUsingDirective(UDir); } @@ -5791,19 +5921,23 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S, case UnqualifiedId::IK_ConstructorName: case UnqualifiedId::IK_ConstructorTemplateId: // C++0x inherited constructors. - if (getLangOptions().CPlusPlus0x) break; - - Diag(Name.getSourceRange().getBegin(), diag::err_using_decl_constructor) + Diag(Name.getLocStart(), + getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_using_decl_constructor : + diag::err_using_decl_constructor) << SS.getRange(); + + if (getLangOpts().CPlusPlus0x) break; + return 0; case UnqualifiedId::IK_DestructorName: - Diag(Name.getSourceRange().getBegin(), diag::err_using_decl_destructor) + Diag(Name.getLocStart(), diag::err_using_decl_destructor) << SS.getRange(); return 0; case UnqualifiedId::IK_TemplateId: - Diag(Name.getSourceRange().getBegin(), diag::err_using_decl_template_id) + Diag(Name.getLocStart(), diag::err_using_decl_template_id) << SourceRange(Name.TemplateId->LAngleLoc, Name.TemplateId->RAngleLoc); return 0; } @@ -5818,7 +5952,7 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S, // talk about access decls instead of using decls in the // diagnostics. if (!HasUsingKeyword) { - UsingLoc = Name.getSourceRange().getBegin(); + UsingLoc = Name.getLocStart(); Diag(UsingLoc, diag::warn_access_decl_deprecated) << FixItHint::CreateInsertion(SS.getRange().getBegin(), "using "); @@ -5883,7 +6017,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 (!getLangOptions().CPlusPlus0x && CurContext->isRecord()) { + if (!getLangOpts().CPlusPlus0x && CurContext->isRecord()) { DeclContext *OrigDC = Orig->getDeclContext(); // Handle enums and anonymous structs. @@ -6148,9 +6282,9 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, return UD; } - // Constructor inheriting using decls get special treatment. + // The normal rules do not apply to inheriting constructor declarations. if (NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName) { - if (CheckInheritedConstructorUsingDecl(UD)) + if (CheckInheritingConstructorUsingDecl(UD)) UD->setInvalidDecl(); return UD; } @@ -6166,6 +6300,13 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, if (!IsInstantiation) R.setHideTags(false); + // For the purposes of this lookup, we have a base object type + // equal to that of the current context. + if (CurContext->isRecord()) { + R.setBaseObjectType( + Context.getTypeDeclType(cast<CXXRecordDecl>(CurContext))); + } + LookupQualifiedName(R, LookupContext); if (R.empty()) { @@ -6220,11 +6361,8 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, } /// Additional checks for a using declaration referring to a constructor name. -bool Sema::CheckInheritedConstructorUsingDecl(UsingDecl *UD) { - if (UD->isTypeName()) { - // FIXME: Cannot specify typename when specifying constructor - return true; - } +bool Sema::CheckInheritingConstructorUsingDecl(UsingDecl *UD) { + assert(!UD->isTypeName() && "expecting a constructor name"); const Type *SourceType = UD->getQualifier()->getAsType(); assert(SourceType && @@ -6239,6 +6377,8 @@ bool Sema::CheckInheritedConstructorUsingDecl(UsingDecl *UD) { CanQualType BaseType = BaseIt->getType()->getCanonicalTypeUnqualified(); if (CanonicalSourceType == BaseType) break; + if (BaseIt->getType()->isDependentType()) + break; } if (BaseIt == BaseE) { @@ -6250,7 +6390,8 @@ bool Sema::CheckInheritedConstructorUsingDecl(UsingDecl *UD) { return true; } - BaseIt->setInheritConstructors(); + if (!CurContext->isDependentContext()) + BaseIt->setInheritConstructors(); return false; } @@ -6365,7 +6506,7 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc, RequireCompleteDeclContext(const_cast<CXXScopeSpec&>(SS), NamedContext)) return true; - if (getLangOptions().CPlusPlus0x) { + if (getLangOpts().CPlusPlus0x) { // 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 @@ -6405,7 +6546,7 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc, // need to be repeated. struct UserData { - llvm::DenseSet<const CXXRecordDecl*> Bases; + llvm::SmallPtrSet<const CXXRecordDecl*, 4> Bases; static bool collect(const CXXRecordDecl *Base, void *OpaqueData) { UserData *Data = reinterpret_cast<UserData*>(OpaqueData); @@ -6485,9 +6626,7 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S, // Warn about shadowing the name of a template parameter. if (Previous.isSingleResult() && Previous.getFoundDecl()->isTemplateParameter()) { - if (DiagnoseTemplateParameterShadow(Name.StartLocation, - Previous.getFoundDecl())) - Invalid = true; + DiagnoseTemplateParameterShadow(Name.StartLocation,Previous.getFoundDecl()); Previous.clear(); } @@ -6633,7 +6772,7 @@ Decl *Sema::ActOnNamespaceAliasDef(Scope *S, if (R.empty()) { if (!TryNamespaceTypoCorrection(*this, R, S, SS, IdentLoc, Ident)) { - Diag(NamespaceLoc, diag::err_expected_namespace_name) << SS.getRange(); + Diag(IdentLoc, diag::err_expected_namespace_name) << SS.getRange(); return 0; } } @@ -6664,7 +6803,7 @@ namespace { ~ImplicitlyDefinedFunctionScope() { S.PopExpressionEvaluationContext(); - S.PopFunctionOrBlockScope(); + S.PopFunctionScopeInfo(); } }; } @@ -6757,16 +6896,12 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( DeclarationName Name = Context.DeclarationNames.getCXXConstructorName(ClassType); DeclarationNameInfo NameInfo(Name, ClassLoc); - CXXConstructorDecl *DefaultCon - = CXXConstructorDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, - Context.getFunctionType(Context.VoidTy, - 0, 0, EPI), - /*TInfo=*/0, - /*isExplicit=*/false, - /*isInline=*/true, - /*isImplicitlyDeclared=*/true, - // FIXME: apply the rules for definitions here - /*isConstexpr=*/false); + CXXConstructorDecl *DefaultCon = CXXConstructorDecl::Create( + Context, ClassDecl, ClassLoc, NameInfo, + Context.getFunctionType(Context.VoidTy, 0, 0, EPI), /*TInfo=*/0, + /*isExplicit=*/false, /*isInline=*/true, /*isImplicitlyDeclared=*/true, + /*isConstexpr=*/ClassDecl->defaultedDefaultConstructorIsConstexpr() && + getLangOpts().CPlusPlus0x); DefaultCon->setAccess(AS_public); DefaultCon->setDefaulted(); DefaultCon->setImplicit(); @@ -6905,7 +7040,6 @@ void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) { Context.getCanonicalType(CtorIt->getType()).getTypePtr()); } - Scope *S = getScopeForContext(ClassDecl); DeclarationName CreatedCtorName = Context.DeclarationNames.getCXXConstructorName( ClassDecl->getTypeForDecl()->getCanonicalTypeUnqualified()); @@ -6927,10 +7061,12 @@ void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) { CtorE = BaseDecl->ctor_end(); CtorIt != CtorE; ++CtorIt) { // Find the using declaration for inheriting this base's constructors. + // FIXME: Don't perform name lookup just to obtain a source location! DeclarationName Name = Context.DeclarationNames.getCXXConstructorName(CanonicalBase); - UsingDecl *UD = dyn_cast_or_null<UsingDecl>( - LookupSingleName(S, Name,SourceLocation(), LookupUsingDeclName)); + LookupResult Result(*this, Name, SourceLocation(), LookupUsingDeclName); + LookupQualifiedName(Result, CurContext); + UsingDecl *UD = Result.getAsSingle<UsingDecl>(); SourceLocation UsingLoc = UD ? UD->getLocation() : ClassDecl->getLocation(); @@ -7041,7 +7177,6 @@ void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) { NewCtor->setParams(ParamDecls); NewCtor->setInheritedConstructor(BaseCtor); - PushOnScopeChains(NewCtor, S, false); ClassDecl->addDecl(NewCtor); result.first->second.second = NewCtor; } @@ -7131,18 +7266,19 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) { // This could be uniqued if it ever proves significant. Destructor->setTypeSourceInfo(Context.getTrivialTypeSourceInfo(Ty)); - if (ShouldDeleteDestructor(Destructor)) - Destructor->setDeletedAsWritten(); - AddOverriddenMethods(ClassDecl, Destructor); - + + if (ShouldDeleteSpecialMember(Destructor, CXXDestructor)) + Destructor->setDeletedAsWritten(); + return Destructor; } void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation, CXXDestructorDecl *Destructor) { assert((Destructor->isDefaulted() && - !Destructor->doesThisDeclarationHaveABody()) && + !Destructor->doesThisDeclarationHaveABody() && + !Destructor->isDeleted()) && "DefineImplicitDestructor - call it for implicit default dtor"); CXXRecordDecl *ClassDecl = Destructor->getParent(); assert(ClassDecl && "DefineImplicitDestructor - invalid destructor"); @@ -7259,8 +7395,8 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, while (F.hasNext()) { NamedDecl *D = F.next(); if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) - if (Copying ? Method->isCopyAssignmentOperator() : - Method->isMoveAssignmentOperator()) + if (Method->isCopyAssignmentOperator() || + (!Copying && Method->isMoveAssignmentOperator())) continue; F.erase(); @@ -7290,15 +7426,18 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, // 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, - T.getTypePtr()), + CanonicalT), Loc); // Create the reference to operator=. ExprResult OpEqualRef = S.BuildMemberReferenceExpr(To, T, Loc, /*isArrow=*/false, SS, - /*FirstQualifierInScope=*/0, OpLookup, + /*TemplateKWLoc=*/SourceLocation(), + /*FirstQualifierInScope=*/0, + OpLookup, /*TemplateArgs=*/0, /*SuppressQualifierCheck=*/true); if (OpEqualRef.isInvalid()) @@ -7339,7 +7478,7 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, // Create the iteration variable. IdentifierInfo *IterationVarName = 0; { - llvm::SmallString<8> Str; + SmallString<8> Str; llvm::raw_svector_ostream OS(Str); OS << "__i" << Depth; IterationVarName = &S.Context.Idents.get(OS.str()); @@ -7356,9 +7495,11 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, // Create a reference to the iteration variable; we'll use this several // times throughout. Expr *IterationVarRef - = S.BuildDeclRefExpr(IterationVar, SizeType, VK_RValue, Loc).take(); + = S.BuildDeclRefExpr(IterationVar, SizeType, VK_LValue, Loc).take(); assert(IterationVarRef && "Reference to invented variable cannot fail!"); - + Expr *IterationVarRefRVal = S.DefaultLvalueConversion(IterationVarRef).take(); + assert(IterationVarRefRVal && "Conversion of invented variable cannot fail!"); + // Create the DeclStmt that holds the iteration variable. Stmt *InitStmt = new (S.Context) DeclStmt(DeclGroupRef(IterationVar),Loc,Loc); @@ -7366,7 +7507,7 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, llvm::APInt Upper = ArrayTy->getSize().zextOrTrunc(S.Context.getTypeSize(SizeType)); Expr *Comparison - = new (S.Context) BinaryOperator(IterationVarRef, + = new (S.Context) BinaryOperator(IterationVarRefRVal, IntegerLiteral::Create(S.Context, Upper, SizeType, Loc), BO_NE, S.Context.BoolTy, VK_RValue, OK_Ordinary, Loc); @@ -7378,9 +7519,11 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, // Subscript the "from" and "to" expressions with the iteration variable. From = AssertSuccess(S.CreateBuiltinArraySubscriptExpr(From, Loc, - IterationVarRef, Loc)); + IterationVarRefRVal, + Loc)); To = AssertSuccess(S.CreateBuiltinArraySubscriptExpr(To, Loc, - IterationVarRef, Loc)); + IterationVarRefRVal, + Loc)); if (!Copying) // Cast to rvalue From = CastForMoving(S, From); @@ -7432,7 +7575,7 @@ Sema::ComputeDefaultedCopyAssignmentExceptionSpecAndConst( &HasConstCopyAssignment); } - // In C++0x, the above citation has "or virtual added" + // In C++11, the above citation has "or virtual" added if (LangOpts.CPlusPlus0x) { for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(), BaseEnd = ClassDecl->vbases_end(); @@ -7565,15 +7708,14 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { PushOnScopeChains(CopyAssignment, S, false); ClassDecl->addDecl(CopyAssignment); - // C++0x [class.copy]p18: - // ... If the class definition declares a move constructor or move - // assignment operator, the implicitly declared copy assignment operator is - // defined as deleted; ... - if (ClassDecl->hasUserDeclaredMoveConstructor() || - ClassDecl->hasUserDeclaredMoveAssignment() || - ShouldDeleteCopyAssignmentOperator(CopyAssignment)) + // 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(); - + AddOverriddenMethods(ClassDecl, CopyAssignment); return CopyAssignment; } @@ -7583,7 +7725,8 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, assert((CopyAssignOperator->isDefaulted() && CopyAssignOperator->isOverloadedOperator() && CopyAssignOperator->getOverloadedOperator() == OO_Equal && - !CopyAssignOperator->doesThisDeclarationHaveABody()) && + !CopyAssignOperator->doesThisDeclarationHaveABody() && + !CopyAssignOperator->isDeleted()) && "DefineImplicitCopyAssignment called for wrong function"); CXXRecordDecl *ClassDecl = CopyAssignOperator->getParent(); @@ -7734,10 +7877,12 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, MemberLookup.resolveKind(); ExprResult From = BuildMemberReferenceExpr(OtherRef, OtherRefType, Loc, /*IsArrow=*/false, - SS, 0, MemberLookup, 0); + SS, SourceLocation(), 0, + MemberLookup, 0); ExprResult To = BuildMemberReferenceExpr(This, This->getType(), Loc, /*IsArrow=*/true, - SS, 0, MemberLookup, 0); + SS, SourceLocation(), 0, + MemberLookup, 0); assert(!From.isInvalid() && "Implicit field reference cannot fail"); assert(!To.isInvalid() && "Implicit field reference cannot fail"); @@ -7869,10 +8014,14 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, CopyAssignOperator->setInvalidDecl(); return; } - - StmtResult Body = ActOnCompoundStmt(Loc, Loc, move_arg(Statements), - /*isStmtExpr=*/false); - assert(!Body.isInvalid() && "Compound statement creation cannot fail"); + + StmtResult Body; + { + CompoundScopeRAII CompoundScope(*this); + Body = ActOnCompoundStmt(Loc, Loc, move_arg(Statements), + /*isStmtExpr=*/false); + assert(!Body.isInvalid() && "Compound statement creation cannot fail"); + } CopyAssignOperator->setBody(Body.takeAs<Stmt>()); if (ASTMutationListener *L = getASTMutationListener()) { @@ -7937,7 +8086,115 @@ Sema::ComputeDefaultedMoveAssignmentExceptionSpec(CXXRecordDecl *ClassDecl) { return ExceptSpec; } +/// Determine whether the class type has any direct or indirect virtual base +/// classes which have a non-trivial move assignment operator. +static bool +hasVirtualBaseWithNonTrivialMoveAssignment(Sema &S, CXXRecordDecl *ClassDecl) { + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(), + BaseEnd = ClassDecl->vbases_end(); + Base != BaseEnd; ++Base) { + CXXRecordDecl *BaseClass = + cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + + // Try to declare the move assignment. If it would be deleted, then the + // class does not have a non-trivial move assignment. + 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()) + return true; + } + + return false; +} + +/// Determine whether the given type either has a move constructor or is +/// trivially copyable. +static bool +hasMoveOrIsTriviallyCopyable(Sema &S, QualType Type, bool IsConstructor) { + Type = S.Context.getBaseElementType(Type); + + // FIXME: Technically, non-trivially-copyable non-class types, such as + // reference types, are supposed to return false here, but that appears + // to be a standard defect. + CXXRecordDecl *ClassDecl = Type->getAsCXXRecordDecl(); + if (!ClassDecl) + return true; + + if (Type.isTriviallyCopyableType(S.Context)) + return true; + + if (IsConstructor) { + if (ClassDecl->needsImplicitMoveConstructor()) + S.DeclareImplicitMoveConstructor(ClassDecl); + return ClassDecl->hasDeclaredMoveConstructor(); + } + + if (ClassDecl->needsImplicitMoveAssignment()) + S.DeclareImplicitMoveAssignment(ClassDecl); + return ClassDecl->hasDeclaredMoveAssignment(); +} + +/// Determine whether all non-static data members and direct or virtual bases +/// of class \p ClassDecl have either a move operation, or are trivially +/// copyable. +static bool subobjectsHaveMoveOrTrivialCopy(Sema &S, CXXRecordDecl *ClassDecl, + bool IsConstructor) { + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), + BaseEnd = ClassDecl->bases_end(); + Base != BaseEnd; ++Base) { + if (Base->isVirtual()) + continue; + + if (!hasMoveOrIsTriviallyCopyable(S, Base->getType(), IsConstructor)) + return false; + } + + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(), + BaseEnd = ClassDecl->vbases_end(); + Base != BaseEnd; ++Base) { + if (!hasMoveOrIsTriviallyCopyable(S, Base->getType(), IsConstructor)) + return false; + } + + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + FieldEnd = ClassDecl->field_end(); + Field != FieldEnd; ++Field) { + if (!hasMoveOrIsTriviallyCopyable(S, (*Field)->getType(), IsConstructor)) + return false; + } + + return true; +} + CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) { + // C++11 [class.copy]p20: + // If the definition of a class X does not explicitly declare a move + // assignment operator, one will be implicitly declared as defaulted + // if and only if: + // + // - [first 4 bullets] + assert(ClassDecl->needsImplicitMoveAssignment()); + + // [Checked after we build the declaration] + // - the move assignment operator would not be implicitly defined as + // deleted, + + // [DR1402]: + // - X has no direct or indirect virtual base class with a non-trivial + // move assignment operator, and + // - each of X's non-static data members and direct or virtual base classes + // has a type that either has a move assignment operator or is trivially + // copyable. + if (hasVirtualBaseWithNonTrivialMoveAssignment(*this, ClassDecl) || + !subobjectsHaveMoveOrTrivialCopy(*this, ClassDecl,/*Constructor*/false)) { + ClassDecl->setFailedImplicitMoveAssignment(); + return 0; + } + // Note: The following rules are largely analoguous to the move // constructor rules. @@ -7985,7 +8242,7 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) { // [...] // - the move assignment operator would not be implicitly defined as // deleted. - if (ShouldDeleteMoveAssignmentOperator(MoveAssignment)) { + if (ShouldDeleteSpecialMember(MoveAssignment, CXXMoveAssignment)) { // Cache this result so that we don't try to generate this over and over // on every lookup, leaking memory and wasting time. ClassDecl->setFailedImplicitMoveAssignment(); @@ -8005,7 +8262,8 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, assert((MoveAssignOperator->isDefaulted() && MoveAssignOperator->isOverloadedOperator() && MoveAssignOperator->getOverloadedOperator() == OO_Equal && - !MoveAssignOperator->doesThisDeclarationHaveABody()) && + !MoveAssignOperator->doesThisDeclarationHaveABody() && + !MoveAssignOperator->isDeleted()) && "DefineImplicitMoveAssignment called for wrong function"); CXXRecordDecl *ClassDecl = MoveAssignOperator->getParent(); @@ -8052,7 +8310,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, // ASTs. Expr *This = ActOnCXXThis(Loc).takeAs<Expr>(); assert(This && "Reference to this cannot fail!"); - + // Assign base classes. bool Invalid = false; for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), @@ -8154,10 +8412,12 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, MemberLookup.resolveKind(); ExprResult From = BuildMemberReferenceExpr(OtherRef, OtherRefType, Loc, /*IsArrow=*/false, - SS, 0, MemberLookup, 0); + SS, SourceLocation(), 0, + MemberLookup, 0); ExprResult To = BuildMemberReferenceExpr(This, This->getType(), Loc, /*IsArrow=*/true, - SS, 0, MemberLookup, 0); + SS, SourceLocation(), 0, + MemberLookup, 0); assert(!From.isInvalid() && "Implicit field reference cannot fail"); assert(!To.isInvalid() && "Implicit field reference cannot fail"); @@ -8299,10 +8559,14 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, MoveAssignOperator->setInvalidDecl(); return; } - - StmtResult Body = ActOnCompoundStmt(Loc, Loc, move_arg(Statements), - /*isStmtExpr=*/false); - assert(!Body.isInvalid() && "Compound statement creation cannot fail"); + + StmtResult Body; + { + CompoundScopeRAII CompoundScope(*this); + Body = ActOnCompoundStmt(Loc, Loc, move_arg(Statements), + /*isStmtExpr=*/false); + assert(!Body.isInvalid() && "Compound statement creation cannot fail"); + } MoveAssignOperator->setBody(Body.takeAs<Stmt>()); if (ASTMutationListener *L = getASTMutationListener()) { @@ -8441,21 +8705,17 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( DeclarationNameInfo NameInfo(Name, ClassLoc); // An implicitly-declared copy constructor is an inline public - // member of its class. - CXXConstructorDecl *CopyConstructor - = CXXConstructorDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, - Context.getFunctionType(Context.VoidTy, - &ArgType, 1, EPI), - /*TInfo=*/0, - /*isExplicit=*/false, - /*isInline=*/true, - /*isImplicitlyDeclared=*/true, - // FIXME: apply the rules for definitions here - /*isConstexpr=*/false); + // member of its class. + CXXConstructorDecl *CopyConstructor = CXXConstructorDecl::Create( + Context, ClassDecl, ClassLoc, NameInfo, + Context.getFunctionType(Context.VoidTy, &ArgType, 1, EPI), /*TInfo=*/0, + /*isExplicit=*/false, /*isInline=*/true, /*isImplicitlyDeclared=*/true, + /*isConstexpr=*/ClassDecl->defaultedCopyConstructorIsConstexpr() && + getLangOpts().CPlusPlus0x); CopyConstructor->setAccess(AS_public); CopyConstructor->setDefaulted(); CopyConstructor->setTrivial(ClassDecl->hasTrivialCopyConstructor()); - + // Note that we have declared this constructor. ++ASTContext::NumImplicitCopyConstructorsDeclared; @@ -8472,15 +8732,14 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( PushOnScopeChains(CopyConstructor, S, false); ClassDecl->addDecl(CopyConstructor); - // C++0x [class.copy]p7: - // ... If the class definition declares a move constructor or move - // assignment operator, the implicitly declared constructor is defined as - // deleted; ... - if (ClassDecl->hasUserDeclaredMoveConstructor() || - ClassDecl->hasUserDeclaredMoveAssignment() || - ShouldDeleteSpecialMember(CopyConstructor, CXXCopyConstructor)) + // C++11 [class.copy]p8: + // ... If the class definition does not explicitly declare a copy + // constructor, there is no user-declared move constructor, and there is no + // user-declared move assignment operator, a copy constructor is implicitly + // declared as defaulted. + if (ShouldDeleteSpecialMember(CopyConstructor, CXXCopyConstructor)) CopyConstructor->setDeletedAsWritten(); - + return CopyConstructor; } @@ -8488,7 +8747,8 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation, CXXConstructorDecl *CopyConstructor) { assert((CopyConstructor->isDefaulted() && CopyConstructor->isCopyConstructor() && - !CopyConstructor->doesThisDeclarationHaveABody()) && + !CopyConstructor->doesThisDeclarationHaveABody() && + !CopyConstructor->isDeleted()) && "DefineImplicitCopyConstructor - call it for implicit copy ctor"); CXXRecordDecl *ClassDecl = CopyConstructor->getParent(); @@ -8503,9 +8763,10 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation, << CXXCopyConstructor << Context.getTagDeclType(ClassDecl); CopyConstructor->setInvalidDecl(); } else { + Sema::CompoundScopeRAII CompoundScope(*this); CopyConstructor->setBody(ActOnCompoundStmt(CopyConstructor->getLocation(), CopyConstructor->getLocation(), - MultiStmtArg(*this, 0, 0), + MultiStmtArg(*this, 0, 0), /*isStmtExpr=*/false) .takeAs<Stmt>()); CopyConstructor->setImplicitlyDefined(true); @@ -8561,12 +8822,7 @@ Sema::ComputeDefaultedMoveCtorExceptionSpec(CXXRecordDecl *ClassDecl) { for (RecordDecl::field_iterator F = ClassDecl->field_begin(), FEnd = ClassDecl->field_end(); F != FEnd; ++F) { - if (F->hasInClassInitializer()) { - if (Expr *E = F->getInClassInitializer()) - ExceptSpec.CalledExpr(E); - else if (!F->isInvalidDecl()) - ExceptSpec.SetDelayed(); - } else if (const RecordType *RecordTy + if (const RecordType *RecordTy = Context.getBaseElementType(F->getType())->getAs<RecordType>()) { CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RecordTy->getDecl()); CXXConstructorDecl *Constructor = LookupMovingConstructor(FieldRecDecl); @@ -8585,6 +8841,25 @@ Sema::ComputeDefaultedMoveCtorExceptionSpec(CXXRecordDecl *ClassDecl) { CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor( CXXRecordDecl *ClassDecl) { + // C++11 [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: + // + // - [first 4 bullets] + assert(ClassDecl->needsImplicitMoveConstructor()); + + // [Checked after we build the declaration] + // - the move assignment operator would not be implicitly defined as + // deleted, + + // [DR1402]: + // - each of X's non-static data members and direct or virtual base classes + // has a type that either has a move constructor or is trivially copyable. + if (!subobjectsHaveMoveOrTrivialCopy(*this, ClassDecl, /*Constructor*/true)) { + ClassDecl->setFailedImplicitMoveConstructor(); + return 0; + } + ImplicitExceptionSpecification Spec( ComputeDefaultedMoveCtorExceptionSpec(ClassDecl)); @@ -8601,21 +8876,17 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor( // C++0x [class.copy]p11: // An implicitly-declared copy/move constructor is an inline public - // member of its class. - CXXConstructorDecl *MoveConstructor - = CXXConstructorDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, - Context.getFunctionType(Context.VoidTy, - &ArgType, 1, EPI), - /*TInfo=*/0, - /*isExplicit=*/false, - /*isInline=*/true, - /*isImplicitlyDeclared=*/true, - // FIXME: apply the rules for definitions here - /*isConstexpr=*/false); + // member of its class. + CXXConstructorDecl *MoveConstructor = CXXConstructorDecl::Create( + Context, ClassDecl, ClassLoc, NameInfo, + Context.getFunctionType(Context.VoidTy, &ArgType, 1, EPI), /*TInfo=*/0, + /*isExplicit=*/false, /*isInline=*/true, /*isImplicitlyDeclared=*/true, + /*isConstexpr=*/ClassDecl->defaultedMoveConstructorIsConstexpr() && + getLangOpts().CPlusPlus0x); MoveConstructor->setAccess(AS_public); MoveConstructor->setDefaulted(); MoveConstructor->setTrivial(ClassDecl->hasTrivialMoveConstructor()); - + // Add the parameter to the constructor. ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveConstructor, ClassLoc, ClassLoc, @@ -8651,7 +8922,8 @@ void Sema::DefineImplicitMoveConstructor(SourceLocation CurrentLocation, CXXConstructorDecl *MoveConstructor) { assert((MoveConstructor->isDefaulted() && MoveConstructor->isMoveConstructor() && - !MoveConstructor->doesThisDeclarationHaveABody()) && + !MoveConstructor->doesThisDeclarationHaveABody() && + !MoveConstructor->isDeleted()) && "DefineImplicitMoveConstructor - call it for implicit move ctor"); CXXRecordDecl *ClassDecl = MoveConstructor->getParent(); @@ -8666,9 +8938,10 @@ void Sema::DefineImplicitMoveConstructor(SourceLocation CurrentLocation, << CXXMoveConstructor << Context.getTagDeclType(ClassDecl); MoveConstructor->setInvalidDecl(); } else { + Sema::CompoundScopeRAII CompoundScope(*this); MoveConstructor->setBody(ActOnCompoundStmt(MoveConstructor->getLocation(), MoveConstructor->getLocation(), - MultiStmtArg(*this, 0, 0), + MultiStmtArg(*this, 0, 0), /*isStmtExpr=*/false) .takeAs<Stmt>()); MoveConstructor->setImplicitlyDefined(true); @@ -8681,6 +8954,133 @@ void Sema::DefineImplicitMoveConstructor(SourceLocation CurrentLocation, } } +bool Sema::isImplicitlyDeleted(FunctionDecl *FD) { + return FD->isDeleted() && + (FD->isDefaulted() || FD->isImplicit()) && + isa<CXXMethodDecl>(FD); +} + +/// \brief Mark the call operator of the given lambda closure type as "used". +static void markLambdaCallOperatorUsed(Sema &S, CXXRecordDecl *Lambda) { + CXXMethodDecl *CallOperator + = cast<CXXMethodDecl>( + *Lambda->lookup( + S.Context.DeclarationNames.getCXXOperatorName(OO_Call)).first); + CallOperator->setReferenced(); + CallOperator->setUsed(); +} + +void Sema::DefineImplicitLambdaToFunctionPointerConversion( + SourceLocation CurrentLocation, + CXXConversionDecl *Conv) +{ + CXXRecordDecl *Lambda = Conv->getParent(); + + // Make sure that the lambda call operator is marked used. + markLambdaCallOperatorUsed(*this, Lambda); + + Conv->setUsed(); + + ImplicitlyDefinedFunctionScope Scope(*this, Conv); + DiagnosticErrorTrap Trap(Diags); + + // Return the address of the __invoke function. + DeclarationName InvokeName = &Context.Idents.get("__invoke"); + CXXMethodDecl *Invoke + = cast<CXXMethodDecl>(*Lambda->lookup(InvokeName).first); + 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->getLocation(), + Conv->getLocation())); + + // Fill in the __invoke function with a dummy implementation. IR generation + // will fill in the actual details. + Invoke->setUsed(); + Invoke->setReferenced(); + Invoke->setBody(new (Context) CompoundStmt(Context, 0, 0, Conv->getLocation(), + Conv->getLocation())); + + if (ASTMutationListener *L = getASTMutationListener()) { + L->CompletedImplicitDefinition(Conv); + L->CompletedImplicitDefinition(Invoke); + } +} + +void Sema::DefineImplicitLambdaToBlockPointerConversion( + SourceLocation CurrentLocation, + CXXConversionDecl *Conv) +{ + Conv->setUsed(); + + ImplicitlyDefinedFunctionScope Scope(*this, Conv); + DiagnosticErrorTrap Trap(Diags); + + // Copy-initialize the lambda object as needed to capture it. + Expr *This = ActOnCXXThis(CurrentLocation).take(); + Expr *DerefThis =CreateBuiltinUnaryOp(CurrentLocation, UO_Deref, This).take(); + + ExprResult BuildBlock = BuildBlockForLambdaConversion(CurrentLocation, + Conv->getLocation(), + Conv, DerefThis); + + // If we're not under ARC, make sure we still get the _Block_copy/autorelease + // behavior. Note that only the general conversion function does this + // (since it's unusable otherwise); in the case where we inline the + // block literal, it has block literal lifetime semantics. + if (!BuildBlock.isInvalid() && !getLangOpts().ObjCAutoRefCount) + BuildBlock = ImplicitCastExpr::Create(Context, BuildBlock.get()->getType(), + CK_CopyAndAutoreleaseBlockObject, + BuildBlock.get(), 0, VK_RValue); + + if (BuildBlock.isInvalid()) { + Diag(CurrentLocation, diag::note_lambda_to_block_conv); + Conv->setInvalidDecl(); + return; + } + + // Create the return statement that returns the block from the conversion + // function. + StmtResult Return = ActOnReturnStmt(Conv->getLocation(), BuildBlock.get()); + if (Return.isInvalid()) { + Diag(CurrentLocation, diag::note_lambda_to_block_conv); + Conv->setInvalidDecl(); + return; + } + + // Set the body of the conversion function. + Stmt *ReturnS = Return.take(); + Conv->setBody(new (Context) CompoundStmt(Context, &ReturnS, 1, + Conv->getLocation(), + Conv->getLocation())); + + // We're done; notify the mutation listener, if any. + if (ASTMutationListener *L = getASTMutationListener()) { + L->CompletedImplicitDefinition(Conv); + } +} + +/// \brief Determine whether the given list arguments contains exactly one +/// "real" (non-default) argument. +static bool hasOneRealArgument(MultiExprArg Args) { + switch (Args.size()) { + case 0: + return false; + + default: + if (!Args.get()[1]->isDefaultArgument()) + return false; + + // fall through + case 1: + return !Args.get()[0]->isDefaultArgument(); + } + + return false; +} + ExprResult Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, CXXConstructorDecl *Constructor, @@ -8702,7 +9102,7 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, // can be omitted by constructing the temporary object // directly into the target of the omitted copy/move if (ConstructKind == CXXConstructExpr::CK_Complete && - Constructor->isCopyOrMoveConstructor() && ExprArgs.size() >= 1) { + Constructor->isCopyOrMoveConstructor() && hasOneRealArgument(ExprArgs)) { Expr *SubExpr = ((Expr **)ExprArgs.get())[0]; Elidable = SubExpr->isTemporaryObject(Context, Constructor->getParent()); } @@ -8732,10 +9132,11 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, CheckNonNullArguments(NonNull, ExprArgs.get(), ConstructLoc); } - MarkDeclarationReferenced(ConstructLoc, Constructor); + MarkFunctionReferenced(ConstructLoc, Constructor); return Owned(CXXConstructExpr::Create(Context, DeclInitType, ConstructLoc, Constructor, Elidable, Exprs, NumExprs, - HadMultipleCandidates, RequiresZeroInit, + HadMultipleCandidates, /*FIXME*/false, + RequiresZeroInit, static_cast<CXXConstructExpr::ConstructionKind>(ConstructKind), ParenRange)); } @@ -8754,7 +9155,7 @@ bool Sema::InitializeVarWithConstructor(VarDecl *VD, Expr *Temp = TempResult.takeAs<Expr>(); CheckImplicitConversions(Temp, VD->getLocation()); - MarkDeclarationReferenced(VD->getLocation(), Constructor); + MarkFunctionReferenced(VD->getLocation(), Constructor); Temp = MaybeCreateExprWithCleanups(Temp); VD->setInit(Temp); @@ -8766,15 +9167,16 @@ void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) { CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Record->getDecl()); if (ClassDecl->isInvalidDecl()) return; - if (ClassDecl->hasTrivialDestructor()) return; + if (ClassDecl->hasIrrelevantDestructor()) return; if (ClassDecl->isDependentContext()) return; CXXDestructorDecl *Destructor = LookupDestructor(ClassDecl); - MarkDeclarationReferenced(VD->getLocation(), Destructor); + MarkFunctionReferenced(VD->getLocation(), Destructor); CheckDestructorAccess(VD->getLocation(), Destructor, PDiag(diag::err_access_dtor_var) << VD->getDeclName() << VD->getType()); + DiagnoseUseOfDecl(Destructor, VD->getLocation()); if (!VD->hasGlobalStorage()) return; @@ -8787,188 +9189,6 @@ void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) { Diag(VD->getLocation(), diag::warn_global_destructor); } -/// AddCXXDirectInitializerToDecl - This action is called immediately after -/// ActOnDeclarator, when a C++ direct initializer is present. -/// e.g: "int x(1);" -void Sema::AddCXXDirectInitializerToDecl(Decl *RealDecl, - SourceLocation LParenLoc, - MultiExprArg Exprs, - SourceLocation RParenLoc, - bool TypeMayContainAuto) { - assert(Exprs.size() != 0 && Exprs.get() && "missing expressions"); - - // If there is no declaration, there was an error parsing it. Just ignore - // the initializer. - if (RealDecl == 0) - return; - - VarDecl *VDecl = dyn_cast<VarDecl>(RealDecl); - if (!VDecl) { - Diag(RealDecl->getLocation(), diag::err_illegal_initializer); - RealDecl->setInvalidDecl(); - return; - } - - // C++0x [decl.spec.auto]p6. Deduce the type which 'auto' stands in for. - if (TypeMayContainAuto && VDecl->getType()->getContainedAutoType()) { - // FIXME: n3225 doesn't actually seem to indicate this is ill-formed - if (Exprs.size() > 1) { - Diag(Exprs.get()[1]->getSourceRange().getBegin(), - diag::err_auto_var_init_multiple_expressions) - << VDecl->getDeclName() << VDecl->getType() - << VDecl->getSourceRange(); - RealDecl->setInvalidDecl(); - return; - } - - Expr *Init = Exprs.get()[0]; - TypeSourceInfo *DeducedType = 0; - if (!DeduceAutoType(VDecl->getTypeSourceInfo(), Init, DeducedType)) - Diag(VDecl->getLocation(), diag::err_auto_var_deduction_failure) - << VDecl->getDeclName() << VDecl->getType() << Init->getType() - << Init->getSourceRange(); - if (!DeducedType) { - RealDecl->setInvalidDecl(); - return; - } - VDecl->setTypeSourceInfo(DeducedType); - VDecl->setType(DeducedType->getType()); - - // In ARC, infer lifetime. - if (getLangOptions().ObjCAutoRefCount && inferObjCARCLifetime(VDecl)) - VDecl->setInvalidDecl(); - - // If this is a redeclaration, check that the type we just deduced matches - // the previously declared type. - if (VarDecl *Old = VDecl->getPreviousDeclaration()) - MergeVarDeclTypes(VDecl, Old); - } - - // We will represent direct-initialization similarly to copy-initialization: - // int x(1); -as-> int x = 1; - // ClassType x(a,b,c); -as-> ClassType x = ClassType(a,b,c); - // - // Clients that want to distinguish between the two forms, can check for - // direct initializer using VarDecl::hasCXXDirectInitializer(). - // A major benefit is that clients that don't particularly care about which - // exactly form was it (like the CodeGen) can handle both cases without - // special case code. - - // C++ 8.5p11: - // The form of initialization (using parentheses or '=') is generally - // insignificant, but does matter when the entity being initialized has a - // class type. - - if (!VDecl->getType()->isDependentType() && - !VDecl->getType()->isIncompleteArrayType() && - RequireCompleteType(VDecl->getLocation(), VDecl->getType(), - diag::err_typecheck_decl_incomplete_type)) { - VDecl->setInvalidDecl(); - return; - } - - // The variable can not have an abstract class type. - if (RequireNonAbstractType(VDecl->getLocation(), VDecl->getType(), - diag::err_abstract_type_in_decl, - AbstractVariableType)) - VDecl->setInvalidDecl(); - - const VarDecl *Def; - if ((Def = VDecl->getDefinition()) && Def != VDecl) { - Diag(VDecl->getLocation(), diag::err_redefinition) - << VDecl->getDeclName(); - Diag(Def->getLocation(), diag::note_previous_definition); - VDecl->setInvalidDecl(); - return; - } - - // C++ [class.static.data]p4 - // If a static data member is of const integral or const - // enumeration type, its declaration in the class definition can - // specify a constant-initializer which shall be an integral - // constant expression (5.19). In that case, the member can appear - // in integral constant expressions. The member shall still be - // defined in a namespace scope if it is used in the program and the - // namespace scope definition shall not contain an initializer. - // - // We already performed a redefinition check above, but for static - // data members we also need to check whether there was an in-class - // declaration with an initializer. - const VarDecl* PrevInit = 0; - if (VDecl->isStaticDataMember() && VDecl->getAnyInitializer(PrevInit)) { - Diag(VDecl->getLocation(), diag::err_redefinition) << VDecl->getDeclName(); - Diag(PrevInit->getLocation(), diag::note_previous_definition); - return; - } - - bool IsDependent = false; - for (unsigned I = 0, N = Exprs.size(); I != N; ++I) { - if (DiagnoseUnexpandedParameterPack(Exprs.get()[I], UPPC_Expression)) { - VDecl->setInvalidDecl(); - return; - } - - if (Exprs.get()[I]->isTypeDependent()) - IsDependent = true; - } - - // If either the declaration has a dependent type or if any of the - // expressions is type-dependent, we represent the initialization - // via a ParenListExpr for later use during template instantiation. - if (VDecl->getType()->isDependentType() || IsDependent) { - // Let clients know that initialization was done with a direct initializer. - VDecl->setCXXDirectInitializer(true); - - // Store the initialization expressions as a ParenListExpr. - unsigned NumExprs = Exprs.size(); - VDecl->setInit(new (Context) ParenListExpr( - Context, LParenLoc, (Expr **)Exprs.release(), NumExprs, RParenLoc, - VDecl->getType().getNonReferenceType())); - return; - } - - // Capture the variable that is being initialized and the style of - // initialization. - InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl); - - // FIXME: Poor source location information. - InitializationKind Kind - = InitializationKind::CreateDirect(VDecl->getLocation(), - LParenLoc, RParenLoc); - - QualType T = VDecl->getType(); - InitializationSequence InitSeq(*this, Entity, Kind, - Exprs.get(), Exprs.size()); - ExprResult Result = InitSeq.Perform(*this, Entity, Kind, move(Exprs), &T); - if (Result.isInvalid()) { - VDecl->setInvalidDecl(); - return; - } else if (T != VDecl->getType()) { - VDecl->setType(T); - Result.get()->setType(T); - } - - - Expr *Init = Result.get(); - CheckImplicitConversions(Init, LParenLoc); - - if (VDecl->isConstexpr() && !VDecl->isInvalidDecl() && - !Init->isValueDependent() && - !Init->isConstantInitializer(Context, - VDecl->getType()->isReferenceType())) { - // FIXME: Improve this diagnostic to explain why the initializer is not - // a constant expression. - Diag(VDecl->getLocation(), diag::err_constexpr_var_requires_const_init) - << VDecl << Init->getSourceRange(); - } - - Init = MaybeCreateExprWithCleanups(Init); - VDecl->setInit(Init); - VDecl->setCXXDirectInitializer(true); - - CheckCompleteVariableDeclaration(VDecl); -} - /// \brief Given a constructor and the set of arguments provided for the /// constructor, convert the arguments and add any required default arguments /// to form a proper call to this constructor. @@ -8978,7 +9198,8 @@ bool Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor, MultiExprArg ArgsPtr, SourceLocation Loc, - ASTOwningVector<Expr*> &ConvertedArgs) { + ASTOwningVector<Expr*> &ConvertedArgs, + bool AllowExplicit) { // FIXME: This duplicates a lot of code from Sema::ConvertArgumentsForCall. unsigned NumArgs = ArgsPtr.size(); Expr **Args = (Expr **)ArgsPtr.get(); @@ -8999,9 +9220,13 @@ Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor, SmallVector<Expr *, 8> AllArgs; bool Invalid = GatherArgumentsForCall(Loc, Constructor, Proto, 0, Args, NumArgs, AllArgs, - CallType); - for (unsigned i =0, size = AllArgs.size(); i < size; i++) - ConvertedArgs.push_back(AllArgs[i]); + CallType, AllowExplicit); + ConvertedArgs.append(AllArgs.begin(), AllArgs.end()); + + DiagnoseSentinelCalls(Constructor, Loc, AllArgs.data(), AllArgs.size()); + + // FIXME: Missing call to CheckFunctionCall or equivalent + return Invalid; } @@ -9270,21 +9495,29 @@ bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) { /// of this literal operator function is well-formed. If so, returns /// false; otherwise, emits appropriate diagnostics and returns true. bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) { - DeclContext *DC = FnDecl->getDeclContext(); - Decl::Kind Kind = DC->getDeclKind(); - if (Kind != Decl::TranslationUnit && Kind != Decl::Namespace && - Kind != Decl::LinkageSpec) { + if (isa<CXXMethodDecl>(FnDecl)) { Diag(FnDecl->getLocation(), diag::err_literal_operator_outside_namespace) << FnDecl->getDeclName(); return true; } + if (FnDecl->isExternC()) { + Diag(FnDecl->getLocation(), diag::err_literal_operator_extern_c); + return true; + } + bool Valid = false; + // This might be the definition of a literal operator template. + FunctionTemplateDecl *TpDecl = FnDecl->getDescribedFunctionTemplate(); + // This might be a specialization of a literal operator template. + if (!TpDecl) + TpDecl = FnDecl->getPrimaryTemplate(); + // template <char...> type operator "" name() is the only valid template // signature, and the only valid signature with no parameters. - if (FnDecl->param_size() == 0) { - if (FunctionTemplateDecl *TpDecl = FnDecl->getDescribedFunctionTemplate()) { + if (TpDecl) { + if (FnDecl->param_size() == 0) { // Must have only one template parameter TemplateParameterList *Params = TpDecl->getTemplateParameters(); if (Params->size() == 1) { @@ -9297,11 +9530,11 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) { Valid = true; } } - } else { + } else if (FnDecl->param_size()) { // Check the first parameter FunctionDecl::param_iterator Param = FnDecl->param_begin(); - QualType T = (*Param)->getType(); + QualType T = (*Param)->getType().getUnqualifiedType(); // unsigned long long int, long double, and any character type are allowed // as the only parameters. @@ -9321,7 +9554,7 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) { if (!PT) goto FinishedParams; T = PT->getPointeeType(); - if (!T.isConstQualified()) + if (!T.isConstQualified() || T.isVolatileQualified()) goto FinishedParams; T = T.getUnqualifiedType(); @@ -9358,30 +9591,28 @@ FinishedParams: return true; } - StringRef LiteralName + // A parameter-declaration-clause containing a default argument is not + // equivalent to any of the permitted forms. + for (FunctionDecl::param_iterator Param = FnDecl->param_begin(), + ParamEnd = FnDecl->param_end(); + Param != ParamEnd; ++Param) { + if ((*Param)->hasDefaultArg()) { + Diag((*Param)->getDefaultArgRange().getBegin(), + diag::err_literal_operator_default_argument) + << (*Param)->getDefaultArgRange(); + break; + } + } + + StringRef LiteralName = FnDecl->getDeclName().getCXXLiteralIdentifier()->getName(); if (LiteralName[0] != '_') { - // C++0x [usrlit.suffix]p1: - // Literal suffix identifiers that do not start with an underscore are - // reserved for future standardization. - bool IsHexFloat = true; - if (LiteralName.size() > 1 && - (LiteralName[0] == 'P' || LiteralName[0] == 'p')) { - for (unsigned I = 1, N = LiteralName.size(); I < N; ++I) { - if (!isdigit(LiteralName[I])) { - IsHexFloat = false; - break; - } - } - } - - if (IsHexFloat) - Diag(FnDecl->getLocation(), diag::warn_user_literal_hexfloat) - << LiteralName; - else - Diag(FnDecl->getLocation(), diag::warn_user_literal_reserved); + // C++11 [usrlit.suffix]p1: + // Literal suffix identifiers that do not start with an underscore + // are reserved for future standardization. + Diag(FnDecl->getLocation(), diag::warn_user_literal_reserved); } - + return false; } @@ -9458,28 +9689,21 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, Invalid = true; } - // GCC allows catching pointers and references to incomplete types - // as an extension; so do we, but we warn by default. - QualType BaseType = ExDeclType; int Mode = 0; // 0 for direct type, 1 for pointer, 2 for reference unsigned DK = diag::err_catch_incomplete; - bool IncompleteCatchIsInvalid = true; if (const PointerType *Ptr = BaseType->getAs<PointerType>()) { BaseType = Ptr->getPointeeType(); Mode = 1; - DK = diag::ext_catch_incomplete_ptr; - IncompleteCatchIsInvalid = false; + DK = diag::err_catch_incomplete_ptr; } else if (const ReferenceType *Ref = BaseType->getAs<ReferenceType>()) { // For the purpose of error recovery, we treat rvalue refs like lvalue refs. BaseType = Ref->getPointeeType(); Mode = 2; - DK = diag::ext_catch_incomplete_ref; - IncompleteCatchIsInvalid = false; + DK = diag::err_catch_incomplete_ref; } if (!Invalid && (Mode == 0 || !BaseType->isVoidType()) && - !BaseType->isDependentType() && RequireCompleteType(Loc, BaseType, DK) && - IncompleteCatchIsInvalid) + !BaseType->isDependentType() && RequireCompleteType(Loc, BaseType, DK)) Invalid = true; if (!Invalid && !ExDeclType->isDependentType() && @@ -9490,7 +9714,7 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, // Only the non-fragile NeXT runtime currently supports C++ catches // of ObjC types, and no runtime supports catching ObjC types by value. - if (!Invalid && getLangOptions().ObjC1) { + if (!Invalid && getLangOpts().ObjC1) { QualType T = ExDeclType; if (const ReferenceType *RT = T->getAs<ReferenceType>()) T = RT->getPointeeType(); @@ -9499,7 +9723,7 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, Diag(Loc, diag::err_objc_object_catch); Invalid = true; } else if (T->isObjCObjectPointerType()) { - if (!getLangOptions().ObjCNonFragileABI) + if (!getLangOpts().ObjCNonFragileABI) Diag(Loc, diag::warn_objc_pointer_cxx_catch_fragile); } } @@ -9508,6 +9732,10 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, ExDeclType, TInfo, SC_None, SC_None); ExDecl->setExceptionVariable(true); + // In ARC, infer 'retaining' for variables of retainable type. + if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(ExDecl)) + Invalid = true; + if (!Invalid && !ExDeclType->isDependentType()) { if (const RecordType *recordType = ExDeclType->getAs<RecordType>()) { // C++ [except.handle]p16: @@ -9578,6 +9806,7 @@ Decl *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) { if (PrevDecl->isTemplateParameter()) { // Maybe we will complain about the shadowed template parameter. DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl); + PrevDecl = 0; } } @@ -9588,7 +9817,7 @@ Decl *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) { } VarDecl *ExDecl = BuildExceptionDeclaration(S, TInfo, - D.getSourceRange().getBegin(), + D.getLocStart(), D.getIdentifierLoc(), D.getIdentifier()); if (Invalid) @@ -9611,17 +9840,24 @@ Decl *Sema::ActOnStaticAssertDeclaration(SourceLocation StaticAssertLoc, StringLiteral *AssertMessage = cast<StringLiteral>(AssertMessageExpr_); if (!AssertExpr->isTypeDependent() && !AssertExpr->isValueDependent()) { - llvm::APSInt Value(32); - if (!AssertExpr->isIntegerConstantExpr(Value, Context)) { - Diag(StaticAssertLoc, - diag::err_static_assert_expression_is_not_constant) << - AssertExpr->getSourceRange(); + // In a static_assert-declaration, the constant-expression shall be a + // constant expression that can be contextually converted to bool. + ExprResult Converted = PerformContextuallyConvertToBool(AssertExpr); + if (Converted.isInvalid()) + return 0; + + llvm::APSInt Cond; + if (VerifyIntegerConstantExpression(Converted.get(), &Cond, + PDiag(diag::err_static_assert_expression_is_not_constant), + /*AllowFold=*/false).isInvalid()) return 0; - } - if (Value == 0) { + if (!Cond) { + llvm::SmallString<256> MsgBuffer; + llvm::raw_svector_ostream Msg(MsgBuffer); + AssertMessage->printPretty(Msg, Context, 0, getPrintingPolicy()); Diag(StaticAssertLoc, diag::err_static_assert_failed) - << AssertMessage->getString() << AssertExpr->getSourceRange(); + << Msg.str() << AssertExpr->getSourceRange(); } } @@ -9638,46 +9874,54 @@ Decl *Sema::ActOnStaticAssertDeclaration(SourceLocation StaticAssertLoc, /// \brief Perform semantic analysis of the given friend type declaration. /// /// \returns A friend declaration that. -FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation FriendLoc, +FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation Loc, + SourceLocation FriendLoc, TypeSourceInfo *TSInfo) { assert(TSInfo && "NULL TypeSourceInfo for friend type declaration"); QualType T = TSInfo->getType(); SourceRange TypeRange = TSInfo->getTypeLoc().getLocalSourceRange(); - if (!getLangOptions().CPlusPlus0x) { - // C++03 [class.friend]p2: - // An elaborated-type-specifier shall be used in a friend declaration - // for a class.* - // - // * The class-key of the elaborated-type-specifier is required. - if (!ActiveTemplateInstantiations.empty()) { - // 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(); - - std::string InsertionText = std::string(" ") + RD->getKindName(); - - Diag(TypeRange.getBegin(), diag::ext_unelaborated_friend_type) - << (unsigned) RD->getTagKind() - << T - << FixItHint::CreateInsertion(PP.getLocForEndOfToken(FriendLoc), - InsertionText); - } else { - Diag(FriendLoc, diag::ext_nonclass_type_friend) - << T - << SourceRange(FriendLoc, TypeRange.getEnd()); - } - } else if (T->getAs<EnumType>()) { - Diag(FriendLoc, diag::ext_enum_friend) + // C++03 [class.friend]p2: + // An elaborated-type-specifier shall be used in a friend declaration + // for a class.* + // + // * The class-key of the elaborated-type-specifier is required. + if (!ActiveTemplateInstantiations.empty()) { + // 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(); + + 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(FriendLoc, + getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_nonclass_type_friend : + diag::ext_nonclass_type_friend) << T << SourceRange(FriendLoc, TypeRange.getEnd()); } + } else if (T->getAs<EnumType>()) { + Diag(FriendLoc, + getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_enum_friend : + diag::ext_enum_friend) + << T + << SourceRange(FriendLoc, TypeRange.getEnd()); } // C++0x [class.friend]p3: @@ -9688,7 +9932,7 @@ FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation FriendLoc, // FIXME: C++0x has some syntactic restrictions on friend type declarations // in [class.friend]p3 that we do not implement. - return FriendDecl::Create(Context, CurContext, FriendLoc, TSInfo, FriendLoc); + return FriendDecl::Create(Context, CurContext, Loc, TSInfo, FriendLoc); } /// Handle a friend tag declaration where the scope specifier was @@ -9732,8 +9976,6 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, if (Invalid) return 0; - assert(SS.isNotEmpty() && "valid templated tag with no SS and no direct?"); - bool isAllExplicitSpecializations = true; for (unsigned I = TempParamLists.size(); I-- > 0; ) { if (TempParamLists.get()[I]->size()) { @@ -9748,6 +9990,18 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, // about the template header and build an appropriate non-templated // friend. TODO: for source fidelity, remember the headers. if (isAllExplicitSpecializations) { + if (SS.isEmpty()) { + bool Owned = false; + bool IsDependent = false; + return ActOnTag(S, TagSpec, TUK_Friend, TagLoc, SS, Name, NameLoc, + Attr, AS_public, + /*ModulePrivateLoc=*/SourceLocation(), + MultiTemplateParamsArg(), Owned, IsDependent, + /*ScopedEnumKWLoc=*/SourceLocation(), + /*ScopedEnumUsesClassTag=*/false, + /*UnderlyingType=*/TypeResult()); + } + NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context); ElaboratedTypeKeyword Keyword = TypeWithKeyword::getKeywordForTagTypeKind(Kind); @@ -9759,12 +10013,12 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T); if (isa<DependentNameType>(T)) { DependentNameTypeLoc TL = cast<DependentNameTypeLoc>(TSI->getTypeLoc()); - TL.setKeywordLoc(TagLoc); + TL.setElaboratedKeywordLoc(TagLoc); TL.setQualifierLoc(QualifierLoc); TL.setNameLoc(NameLoc); } else { ElaboratedTypeLoc TL = cast<ElaboratedTypeLoc>(TSI->getTypeLoc()); - TL.setKeywordLoc(TagLoc); + TL.setElaboratedKeywordLoc(TagLoc); TL.setQualifierLoc(QualifierLoc); cast<TypeSpecTypeLoc>(TL.getNamedTypeLoc()).setNameLoc(NameLoc); } @@ -9775,6 +10029,10 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, CurContext->addDecl(Friend); return Friend; } + + assert(SS.isNotEmpty() && "valid templated tag with no SS and no direct?"); + + // Handle the case of a templated-scope friend class. e.g. // template <class T> class A<T>::B; @@ -9783,7 +10041,7 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, QualType T = Context.getDependentNameType(ETK, SS.getScopeRep(), Name); TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T); DependentNameTypeLoc TL = cast<DependentNameTypeLoc>(TSI->getTypeLoc()); - TL.setKeywordLoc(TagLoc); + TL.setElaboratedKeywordLoc(TagLoc); TL.setQualifierLoc(SS.getWithLocInContext(Context)); TL.setNameLoc(NameLoc); @@ -9815,7 +10073,7 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, /// template <> template <class T> friend class A<int>::B; Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, MultiTemplateParamsArg TempParams) { - SourceLocation Loc = DS.getSourceRange().getBegin(); + SourceLocation Loc = DS.getLocStart(); assert(DS.isFriendSpecified()); assert(DS.getStorageClassSpec() == DeclSpec::SCS_unspecified); @@ -9871,7 +10129,7 @@ Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, TSI, DS.getFriendSpecLoc()); else - D = CheckFriendTypeDecl(DS.getFriendSpecLoc(), TSI); + D = CheckFriendTypeDecl(Loc, DS.getFriendSpecLoc(), TSI); if (!D) return 0; @@ -9977,7 +10235,7 @@ Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, // declarations should stop at the nearest enclosing namespace, // not that they should only consider the nearest enclosing // namespace. - while (DC->isRecord()) + while (DC->isRecord() || DC->isTransparentContext()) DC = DC->getParent(); LookupQualifiedName(Previous, DC); @@ -9996,15 +10254,17 @@ Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, // C++ [class.friend]p1: A friend of a class is a function or // class that is not a member of the class . . . - // C++0x changes this for both friend types and functions. + // 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) - && !getLangOptions().CPlusPlus0x) - Diag(DS.getFriendSpecLoc(), diag::err_friend_is_member); + 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: // A function can be defined in a friend declaration of a class if and // only if the class is a non-local class (9.8), the function name is @@ -10046,7 +10306,10 @@ Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, // C++ [class.friend]p1: A friend of a class is a function or // class that is not a member of the class . . . if (DC->Equals(CurContext)) - Diag(DS.getFriendSpecLoc(), diag::err_friend_is_member); + Diag(DS.getFriendSpecLoc(), + getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_friend_is_member : + diag::err_friend_is_member); if (D.isFunctionDefinition()) { // C++ [class.friend]p6: @@ -10093,6 +10356,15 @@ Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, } } + // FIXME: This is an egregious hack to cope with cases where the scope stack + // does not contain the declaration context, i.e., in an out-of-line + // definition of a class. + Scope FakeDCScope(S, Scope::DeclScope, Diags); + if (!DCScope) { + FakeDCScope.setEntity(DC); + DCScope = &FakeDCScope; + } + bool AddToScope = true; NamedDecl *ND = ActOnFunctionDeclarator(DCScope, D, DC, TInfo, Previous, move(TemplateParams), AddToScope); @@ -10109,7 +10381,7 @@ Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, // lookup context is in lexical scope. if (!CurContext->isDependentContext()) { DC = DC->getRedeclContext(); - DC->makeDeclVisibleInContext(ND, /* Recoverable=*/ false); + DC->makeDeclVisibleInContext(ND); if (Scope *EnclosingScope = getScopeForDeclContext(S, DC)) PushOnScopeChains(ND, EnclosingScope, /*AddToContext=*/ false); } @@ -10145,13 +10417,42 @@ void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) { Diag(DelLoc, diag::err_deleted_non_function); return; } - if (const FunctionDecl *Prev = Fn->getPreviousDeclaration()) { + if (const FunctionDecl *Prev = Fn->getPreviousDecl()) { Diag(DelLoc, diag::err_deleted_decl_not_first); Diag(Prev->getLocation(), diag::note_previous_declaration); // If the declaration wasn't the first, we delete the function anyway for // recovery. } Fn->setDeletedAsWritten(); + + CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Dcl); + if (!MD) + 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; + } } void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) { @@ -10245,7 +10546,7 @@ static void SearchForReturnInStmt(Sema &Self, Stmt *S) { if (!SubStmt) continue; if (isa<ReturnStmt>(SubStmt)) - Self.Diag(SubStmt->getSourceRange().getBegin(), + Self.Diag(SubStmt->getLocStart(), diag::err_return_in_constructor_handler); if (!isa<Expr>(SubStmt)) SearchForReturnInStmt(Self, SubStmt); @@ -10376,6 +10677,14 @@ bool Sema::CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange) { return true; } +/// \brief Determine whether the given declaration is a static data member. +static bool isStaticDataMember(Decl *D) { + VarDecl *Var = dyn_cast_or_null<VarDecl>(D); + if (!Var) + return false; + + return Var->isStaticDataMember(); +} /// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse /// an initializer for the out-of-line declaration 'Dcl'. The scope /// is a fresh scope pushed for just this purpose. @@ -10391,6 +10700,12 @@ void Sema::ActOnCXXEnterDeclInitializer(Scope *S, Decl *D) { // int foo::bar; assert(D->isOutOfLine()); EnterDeclaratorContext(S, D->getDeclContext()); + + // If we are parsing the initializer for a static data member, push a + // new expression evaluation context that is associated with this static + // data member. + if (isStaticDataMember(D)) + PushExpressionEvaluationContext(PotentiallyEvaluated, D); } /// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an @@ -10399,6 +10714,9 @@ void Sema::ActOnCXXExitDeclInitializer(Scope *S, Decl *D) { // If there is no declaration, there was an error parsing it. if (D == 0 || D->isInvalidDecl()) return; + if (isStaticDataMember(D)) + PopExpressionEvaluationContext(); + assert(D->isOutOfLine()); ExitDeclaratorContext(S); } @@ -10560,7 +10878,10 @@ bool Sema::DefineUsedVTables() { if (!KeyFunction || (KeyFunction->hasBody(KeyFunctionDef) && KeyFunctionDef->isInlined())) - Diag(Class->getLocation(), diag::warn_weak_vtable) << Class; + Diag(Class->getLocation(), Class->getTemplateSpecializationKind() == + TSK_ExplicitInstantiationDefinition + ? diag::warn_weak_template_vtable : diag::warn_weak_vtable) + << Class; } } VTableUses.clear(); @@ -10577,7 +10898,7 @@ void Sema::MarkVirtualMembersReferenced(SourceLocation Loc, // C++ [basic.def.odr]p2: // [...] A virtual member function is used if it is not pure. [...] if (MD->isVirtual() && !MD->isPure()) - MarkDeclarationReferenced(Loc, MD); + MarkFunctionReferenced(Loc, MD); } // Only classes that have virtual bases need a VTT. @@ -10597,7 +10918,7 @@ void Sema::MarkVirtualMembersReferenced(SourceLocation Loc, /// SetIvarInitializers - This routine builds initialization ASTs for the /// Objective-C implementation whose ivars need be initialized. void Sema::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) { - if (!getLangOptions().CPlusPlus) + if (!getLangOpts().CPlusPlus) return; if (ObjCInterfaceDecl *OID = ObjCImplementation->getClassInterface()) { SmallVector<ObjCIvarDecl*, 8> ivars; @@ -10637,7 +10958,7 @@ void Sema::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) { ->getAs<RecordType>()) { CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl()); if (CXXDestructorDecl *Destructor = LookupDestructor(RD)) { - MarkDeclarationReferenced(Field->getLocation(), Destructor); + MarkFunctionReferenced(Field->getLocation(), Destructor); CheckDestructorAccess(Field->getLocation(), Destructor, PDiag(diag::err_access_dtor_ivar) << Context.getBaseElementType(Field->getType())); |