diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2016-12-26 20:36:37 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2016-12-26 20:36:37 +0000 |
commit | b6d42e34c27d79488e27db71466f4e5cece05910 (patch) | |
tree | ab60b4cdd6e430dda1f292a46a77ddb744723f31 /contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp | |
parent | d76705554f5443404be5a5e89f2f5f5ebf42cf98 (diff) | |
download | src-test2-b6d42e34c27d79488e27db71466f4e5cece05910.tar.gz src-test2-b6d42e34c27d79488e27db71466f4e5cece05910.zip |
Notes
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp | 1414 |
1 files changed, 802 insertions, 612 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp index 82d81a85fa90..e161c87f1739 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp @@ -471,7 +471,7 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, continue; } - // We found our guy. + // We found the right previous declaration. break; } @@ -3356,34 +3356,7 @@ BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, ExprResult BaseInit; switch (ImplicitInitKind) { - case IIK_Inherit: { - const CXXRecordDecl *Inherited = - Constructor->getInheritedConstructor()->getParent(); - const CXXRecordDecl *Base = BaseSpec->getType()->getAsCXXRecordDecl(); - if (Base && Inherited->getCanonicalDecl() == Base->getCanonicalDecl()) { - // C++11 [class.inhctor]p8: - // Each expression in the expression-list is of the form - // static_cast<T&&>(p), where p is the name of the corresponding - // constructor parameter and T is the declared type of p. - SmallVector<Expr*, 16> Args; - for (unsigned I = 0, E = Constructor->getNumParams(); I != E; ++I) { - ParmVarDecl *PD = Constructor->getParamDecl(I); - ExprResult ArgExpr = - SemaRef.BuildDeclRefExpr(PD, PD->getType().getNonReferenceType(), - VK_LValue, SourceLocation()); - if (ArgExpr.isInvalid()) - return true; - Args.push_back(CastForMoving(SemaRef, ArgExpr.get(), PD->getType())); - } - - InitializationKind InitKind = InitializationKind::CreateDirect( - Constructor->getLocation(), SourceLocation(), SourceLocation()); - InitializationSequence InitSeq(SemaRef, InitEntity, InitKind, Args); - BaseInit = InitSeq.Perform(SemaRef, InitEntity, InitKind, Args); - break; - } - } - // Fall through. + case IIK_Inherit: case IIK_Default: { InitializationKind InitKind = InitializationKind::CreateDefault(Constructor->getLocation()); @@ -3694,12 +3667,12 @@ struct BaseAndFieldInfo { BaseAndFieldInfo(Sema &S, CXXConstructorDecl *Ctor, bool ErrorsInInits) : S(S), Ctor(Ctor), AnyErrorsInInits(ErrorsInInits) { bool Generated = Ctor->isImplicit() || Ctor->isDefaulted(); - if (Generated && Ctor->isCopyConstructor()) + if (Ctor->getInheritedConstructor()) + IIK = IIK_Inherit; + else if (Generated && Ctor->isCopyConstructor()) IIK = IIK_Copy; else if (Generated && Ctor->isMoveConstructor()) IIK = IIK_Move; - else if (Ctor->getInheritedConstructor()) - IIK = IIK_Inherit; else IIK = IIK_Default; } @@ -4774,7 +4747,6 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) { // The class is either imported or exported. const bool ClassExported = ClassAttr->getKind() == attr::DLLExport; - const bool ClassImported = !ClassExported; TemplateSpecializationKind TSK = Class->getTemplateSpecializationKind(); @@ -4809,11 +4781,20 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) { if (!Context.getTargetInfo().getCXXABI().isMicrosoft()) continue; - // MSVC versions before 2015 don't export the move assignment operators, - // so don't attempt to import them if we have a definition. - if (ClassImported && MD->isMoveAssignmentOperator() && + // MSVC versions before 2015 don't export the move assignment operators + // and move constructor, so don't attempt to import/export them if + // we have a definition. + auto *Ctor = dyn_cast<CXXConstructorDecl>(MD); + if ((MD->isMoveAssignmentOperator() || + (Ctor && Ctor->isMoveConstructor())) && !getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015)) continue; + + // MSVC2015 doesn't export trivial defaulted x-tor but copy assign + // operator is exported anyway. + if (getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015) && + (Ctor || isa<CXXDestructorDecl>(MD)) && MD->isTrivial()) + continue; } } @@ -4887,6 +4868,33 @@ void Sema::propagateDLLAttrToBaseClassTemplate( } } +static void DefineImplicitSpecialMember(Sema &S, CXXMethodDecl *MD, + SourceLocation DefaultLoc) { + switch (S.getSpecialMember(MD)) { + case Sema::CXXDefaultConstructor: + S.DefineImplicitDefaultConstructor(DefaultLoc, + cast<CXXConstructorDecl>(MD)); + break; + case Sema::CXXCopyConstructor: + S.DefineImplicitCopyConstructor(DefaultLoc, cast<CXXConstructorDecl>(MD)); + break; + case Sema::CXXCopyAssignment: + S.DefineImplicitCopyAssignment(DefaultLoc, MD); + break; + case Sema::CXXDestructor: + S.DefineImplicitDestructor(DefaultLoc, cast<CXXDestructorDecl>(MD)); + break; + case Sema::CXXMoveConstructor: + S.DefineImplicitMoveConstructor(DefaultLoc, cast<CXXConstructorDecl>(MD)); + break; + case Sema::CXXMoveAssignment: + S.DefineImplicitMoveAssignment(DefaultLoc, MD); + break; + case Sema::CXXInvalid: + llvm_unreachable("Invalid special member."); + } +} + /// \brief Perform semantic checks on a class definition that has been /// completing, introducing implicitly-declared members, checking for /// abstract types, etc. @@ -4982,8 +4990,8 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { // For an explicitly defaulted or deleted special member, we defer // determining triviality until the class is complete. That time is now! + CXXSpecialMember CSM = getSpecialMember(M); if (!M->isImplicit() && !M->isUserProvided()) { - CXXSpecialMember CSM = getSpecialMember(M); if (CSM != CXXInvalid) { M->setTrivial(SpecialMemberIsTrivial(M, CSM)); @@ -4991,6 +4999,20 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { Record->finishedDefaultedOrDeletedMember(M); } } + + if (!M->isInvalidDecl() && M->isExplicitlyDefaulted() && + M->hasAttr<DLLExportAttr>()) { + if (getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015) && + M->isTrivial() && + (CSM == CXXDefaultConstructor || CSM == CXXCopyConstructor || + CSM == CXXDestructor)) + M->dropAttr<DLLExportAttr>(); + + if (M->hasAttr<DLLExportAttr>()) { + DefineImplicitSpecialMember(*this, M, M->getLocation()); + ActOnFinishInlineFunctionDef(M); + } + } } } @@ -5016,15 +5038,6 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { Diag(Record->getLocation(), diag::warn_cxx_ms_struct); } - // Declare inheriting constructors. We do this eagerly here because: - // - The standard requires an eager diagnostic for conflicting inheriting - // constructors from different classes. - // - The lazy declaration of the other implicit constructors is so as to not - // waste space and performance on classes that are not meant to be - // instantiated (e.g. meta-functions). This doesn't apply to classes that - // have inheriting constructors. - DeclareInheritingConstructors(Record); - checkClassLevelDLLAttribute(Record); } @@ -5058,11 +5071,108 @@ static Sema::SpecialMemberOverloadResult *lookupCallFromSpecialMember( LHSQuals & Qualifiers::Volatile); } +class Sema::InheritedConstructorInfo { + Sema &S; + SourceLocation UseLoc; + + /// A mapping from the base classes through which the constructor was + /// inherited to the using shadow declaration in that base class (or a null + /// pointer if the constructor was declared in that base class). + llvm::DenseMap<CXXRecordDecl *, ConstructorUsingShadowDecl *> + InheritedFromBases; + +public: + InheritedConstructorInfo(Sema &S, SourceLocation UseLoc, + ConstructorUsingShadowDecl *Shadow) + : S(S), UseLoc(UseLoc) { + bool DiagnosedMultipleConstructedBases = false; + CXXRecordDecl *ConstructedBase = nullptr; + UsingDecl *ConstructedBaseUsing = nullptr; + + // Find the set of such base class subobjects and check that there's a + // unique constructed subobject. + for (auto *D : Shadow->redecls()) { + auto *DShadow = cast<ConstructorUsingShadowDecl>(D); + auto *DNominatedBase = DShadow->getNominatedBaseClass(); + auto *DConstructedBase = DShadow->getConstructedBaseClass(); + + InheritedFromBases.insert( + std::make_pair(DNominatedBase->getCanonicalDecl(), + DShadow->getNominatedBaseClassShadowDecl())); + if (DShadow->constructsVirtualBase()) + InheritedFromBases.insert( + std::make_pair(DConstructedBase->getCanonicalDecl(), + DShadow->getConstructedBaseClassShadowDecl())); + else + assert(DNominatedBase == DConstructedBase); + + // [class.inhctor.init]p2: + // If the constructor was inherited from multiple base class subobjects + // of type B, the program is ill-formed. + if (!ConstructedBase) { + ConstructedBase = DConstructedBase; + ConstructedBaseUsing = D->getUsingDecl(); + } else if (ConstructedBase != DConstructedBase && + !Shadow->isInvalidDecl()) { + if (!DiagnosedMultipleConstructedBases) { + S.Diag(UseLoc, diag::err_ambiguous_inherited_constructor) + << Shadow->getTargetDecl(); + S.Diag(ConstructedBaseUsing->getLocation(), + diag::note_ambiguous_inherited_constructor_using) + << ConstructedBase; + DiagnosedMultipleConstructedBases = true; + } + S.Diag(D->getUsingDecl()->getLocation(), + diag::note_ambiguous_inherited_constructor_using) + << DConstructedBase; + } + } + + if (DiagnosedMultipleConstructedBases) + Shadow->setInvalidDecl(); + } + + /// Find the constructor to use for inherited construction of a base class, + /// and whether that base class constructor inherits the constructor from a + /// virtual base class (in which case it won't actually invoke it). + std::pair<CXXConstructorDecl *, bool> + findConstructorForBase(CXXRecordDecl *Base, CXXConstructorDecl *Ctor) const { + auto It = InheritedFromBases.find(Base->getCanonicalDecl()); + if (It == InheritedFromBases.end()) + return std::make_pair(nullptr, false); + + // This is an intermediary class. + if (It->second) + return std::make_pair( + S.findInheritingConstructor(UseLoc, Ctor, It->second), + It->second->constructsVirtualBase()); + + // This is the base class from which the constructor was inherited. + return std::make_pair(Ctor, false); + } +}; + /// Is the special member function which would be selected to perform the /// specified operation on the specified class type a constexpr constructor? -static bool specialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl, - Sema::CXXSpecialMember CSM, - unsigned Quals, bool ConstRHS) { +static bool +specialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl, + Sema::CXXSpecialMember CSM, unsigned Quals, + bool ConstRHS, + CXXConstructorDecl *InheritedCtor = nullptr, + Sema::InheritedConstructorInfo *Inherited = nullptr) { + // If we're inheriting a constructor, see if we need to call it for this base + // class. + if (InheritedCtor) { + assert(CSM == Sema::CXXDefaultConstructor); + auto BaseCtor = + Inherited->findConstructorForBase(ClassDecl, InheritedCtor).first; + if (BaseCtor) + return BaseCtor->isConstexpr(); + } + + if (CSM == Sema::CXXDefaultConstructor) + return ClassDecl->hasConstexprDefaultConstructor(); + Sema::SpecialMemberOverloadResult *SMOR = lookupCallFromSpecialMember(S, ClassDecl, CSM, Quals, ConstRHS); if (!SMOR || !SMOR->getMethod()) @@ -5074,9 +5184,10 @@ static bool specialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl, /// Determine whether the specified special member function would be constexpr /// if it were implicitly defined. -static bool defaultedSpecialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl, - Sema::CXXSpecialMember CSM, - bool ConstArg) { +static bool defaultedSpecialMemberIsConstexpr( + Sema &S, CXXRecordDecl *ClassDecl, Sema::CXXSpecialMember CSM, + bool ConstArg, CXXConstructorDecl *InheritedCtor = nullptr, + Sema::InheritedConstructorInfo *Inherited = nullptr) { if (!S.getLangOpts().CPlusPlus11) return false; @@ -5085,6 +5196,8 @@ static bool defaultedSpecialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl, bool Ctor = true; switch (CSM) { case Sema::CXXDefaultConstructor: + if (Inherited) + break; // Since default constructor lookup is essentially trivial (and cannot // involve, for instance, template instantiation), we compute whether a // defaulted default constructor is constexpr directly within CXXRecordDecl. @@ -5119,7 +5232,10 @@ static bool defaultedSpecialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl, // will be initialized (if the constructor isn't deleted), we just don't know // which one. if (Ctor && ClassDecl->isUnion()) - return true; + return CSM == Sema::CXXDefaultConstructor + ? ClassDecl->hasInClassInitializer() || + !ClassDecl->hasVariantMembers() + : true; // -- the class shall not have any virtual base classes; if (Ctor && ClassDecl->getNumVBases()) @@ -5139,7 +5255,8 @@ static bool defaultedSpecialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl, if (!BaseType) continue; CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl()); - if (!specialMemberIsConstexpr(S, BaseClassDecl, CSM, 0, ConstArg)) + if (!specialMemberIsConstexpr(S, BaseClassDecl, CSM, 0, ConstArg, + InheritedCtor, Inherited)) return false; } @@ -5153,6 +5270,8 @@ static bool defaultedSpecialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl, for (const auto *F : ClassDecl->fields()) { if (F->isInvalidDecl()) continue; + if (CSM == Sema::CXXDefaultConstructor && F->hasInClassInitializer()) + continue; QualType BaseType = S.Context.getBaseElementType(F->getType()); if (const RecordType *RecordTy = BaseType->getAs<RecordType>()) { CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RecordTy->getDecl()); @@ -5160,6 +5279,8 @@ static bool defaultedSpecialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl, BaseType.getCVRQualifiers(), ConstArg && !F->isMutable())) return false; + } else if (CSM == Sema::CXXDefaultConstructor) { + return false; } } @@ -5187,7 +5308,8 @@ computeImplicitExceptionSpec(Sema &S, SourceLocation Loc, CXXMethodDecl *MD) { } assert(cast<CXXConstructorDecl>(MD)->getInheritedConstructor() && "only special members have implicit exception specs"); - return S.ComputeInheritingCtorExceptionSpec(cast<CXXConstructorDecl>(MD)); + return S.ComputeInheritingCtorExceptionSpec(Loc, + cast<CXXConstructorDecl>(MD)); } static FunctionProtoType::ExtProtoInfo getImplicitMethodEPI(Sema &S, @@ -5384,7 +5506,7 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { // [For a] user-provided explicitly-defaulted function [...] if such a // function is implicitly defined as deleted, the program is ill-formed. Diag(MD->getLocation(), diag::err_out_of_line_default_deletes) << CSM; - ShouldDeleteSpecialMember(MD, CSM, /*Diagnose*/true); + ShouldDeleteSpecialMember(MD, CSM, nullptr, /*Diagnose*/true); HadError = true; } } @@ -5445,6 +5567,7 @@ struct SpecialMemberDeletionInfo { Sema &S; CXXMethodDecl *MD; Sema::CXXSpecialMember CSM; + Sema::InheritedConstructorInfo *ICI; bool Diagnose; // Properties of the special member, computed for convenience. @@ -5454,11 +5577,11 @@ struct SpecialMemberDeletionInfo { 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), Loc(MD->getLocation()), - AllFieldsAreConst(true) { + Sema::CXXSpecialMember CSM, + Sema::InheritedConstructorInfo *ICI, bool Diagnose) + : S(S), MD(MD), CSM(CSM), ICI(ICI), Diagnose(Diagnose), + IsConstructor(false), IsAssignment(false), IsMove(false), + ConstArg(false), Loc(MD->getLocation()), AllFieldsAreConst(true) { switch (CSM) { case Sema::CXXDefaultConstructor: case Sema::CXXCopyConstructor: @@ -5490,6 +5613,10 @@ struct SpecialMemberDeletionInfo { bool inUnion() const { return MD->getParent()->isUnion(); } + Sema::CXXSpecialMember getEffectiveCSM() { + return ICI ? Sema::CXXInvalid : CSM; + } + /// Look up the corresponding special member in the given class. Sema::SpecialMemberOverloadResult *lookupIn(CXXRecordDecl *Class, unsigned Quals, bool IsMutable) { @@ -5566,13 +5693,13 @@ bool SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall( if (Field) { S.Diag(Field->getLocation(), diag::note_deleted_special_member_class_subobject) - << CSM << MD->getParent() << /*IsField*/true + << getEffectiveCSM() << 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 + << getEffectiveCSM() << MD->getParent() << /*IsField*/false << Base->getType() << DiagKind << IsDtorCallInCtor; } @@ -5631,7 +5758,29 @@ bool SpecialMemberDeletionInfo::shouldDeleteForBase(CXXBaseSpecifier *Base) { CXXRecordDecl *BaseClass = Base->getType()->getAsCXXRecordDecl(); // If program is correct, BaseClass cannot be null, but if it is, the error // must be reported elsewhere. - return BaseClass && shouldDeleteForClassSubobject(BaseClass, Base, 0); + if (!BaseClass) + return false; + // If we have an inheriting constructor, check whether we're calling an + // inherited constructor instead of a default constructor. + if (ICI) { + assert(CSM == Sema::CXXDefaultConstructor); + auto *BaseCtor = + ICI->findConstructorForBase(BaseClass, cast<CXXConstructorDecl>(MD) + ->getInheritedConstructor() + .getConstructor()) + .first; + if (BaseCtor) { + if (BaseCtor->isDeleted() && Diagnose) { + S.Diag(Base->getLocStart(), + diag::note_deleted_special_member_class_subobject) + << getEffectiveCSM() << MD->getParent() << /*IsField*/false + << Base->getType() << /*Deleted*/1 << /*IsDtorCallInCtor*/false; + S.NoteDeletedFunction(BaseCtor); + } + return BaseCtor->isDeleted(); + } + } + return shouldDeleteForClassSubobject(BaseClass, Base, 0); } /// Check whether we should delete a special member function due to the class @@ -5646,7 +5795,7 @@ bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) { if (FieldType->isReferenceType() && !FD->hasInClassInitializer()) { if (Diagnose) S.Diag(FD->getLocation(), diag::note_deleted_default_ctor_uninit_field) - << MD->getParent() << FD << FieldType << /*Reference*/0; + << !!ICI << MD->getParent() << FD << FieldType << /*Reference*/0; return true; } // C++11 [class.ctor]p5: any non-variant non-static data member of @@ -5658,7 +5807,7 @@ bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) { (!FieldRecord || !FieldRecord->hasUserProvidedDefaultConstructor())) { if (Diagnose) S.Diag(FD->getLocation(), diag::note_deleted_default_ctor_uninit_field) - << MD->getParent() << FD << FD->getType() << /*Const*/1; + << !!ICI << MD->getParent() << FD << FD->getType() << /*Const*/1; return true; } @@ -5717,7 +5866,7 @@ bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) { if (Diagnose) S.Diag(FieldRecord->getLocation(), diag::note_deleted_default_ctor_all_const) - << MD->getParent() << /*anonymous union*/1; + << !!ICI << MD->getParent() << /*anonymous union*/1; return true; } @@ -5745,7 +5894,7 @@ bool SpecialMemberDeletionInfo::shouldDeleteForAllConstMembers() { if (Diagnose) S.Diag(MD->getParent()->getLocation(), diag::note_deleted_default_ctor_all_const) - << MD->getParent() << /*not anonymous union*/0; + << !!ICI << MD->getParent() << /*not anonymous union*/0; return true; } return false; @@ -5755,6 +5904,7 @@ bool SpecialMemberDeletionInfo::shouldDeleteForAllConstMembers() { /// 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, + InheritedConstructorInfo *ICI, bool Diagnose) { if (MD->isInvalidDecl()) return false; @@ -5844,7 +5994,7 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, } } - SpecialMemberDeletionInfo SMI(*this, MD, CSM, Diagnose); + SpecialMemberDeletionInfo SMI(*this, MD, CSM, ICI, Diagnose); for (auto &BI : RD->bases()) if (!BI.isVirtual() && @@ -6452,27 +6602,33 @@ void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, /// [special]p1). This routine can only be executed just before the /// definition of the class is complete. void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { - if (!ClassDecl->hasUserDeclaredConstructor()) + if (ClassDecl->needsImplicitDefaultConstructor()) { ++ASTContext::NumImplicitDefaultConstructors; - if (!ClassDecl->hasUserDeclaredCopyConstructor()) { + if (ClassDecl->hasInheritedConstructor()) + DeclareImplicitDefaultConstructor(ClassDecl); + } + + if (ClassDecl->needsImplicitCopyConstructor()) { ++ASTContext::NumImplicitCopyConstructors; // If the properties or semantics of the copy constructor couldn't be // determined while the class was being declared, force a declaration // of it now. - if (ClassDecl->needsOverloadResolutionForCopyConstructor()) + if (ClassDecl->needsOverloadResolutionForCopyConstructor() || + ClassDecl->hasInheritedConstructor()) DeclareImplicitCopyConstructor(ClassDecl); } if (getLangOpts().CPlusPlus11 && ClassDecl->needsImplicitMoveConstructor()) { ++ASTContext::NumImplicitMoveConstructors; - if (ClassDecl->needsOverloadResolutionForMoveConstructor()) + if (ClassDecl->needsOverloadResolutionForMoveConstructor() || + ClassDecl->hasInheritedConstructor()) DeclareImplicitMoveConstructor(ClassDecl); } - if (!ClassDecl->hasUserDeclaredCopyAssignment()) { + if (ClassDecl->needsImplicitCopyAssignment()) { ++ASTContext::NumImplicitCopyAssignmentOperators; // If we have a dynamic class, then the copy assignment operator may be @@ -6480,7 +6636,8 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { // it shows up in the right place in the vtable and that we diagnose // problems with the implicit exception specification. if (ClassDecl->isDynamicClass() || - ClassDecl->needsOverloadResolutionForCopyAssignment()) + ClassDecl->needsOverloadResolutionForCopyAssignment() || + ClassDecl->hasInheritedAssignment()) DeclareImplicitCopyAssignment(ClassDecl); } @@ -6489,11 +6646,12 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { // Likewise for the move assignment operator. if (ClassDecl->isDynamicClass() || - ClassDecl->needsOverloadResolutionForMoveAssignment()) + ClassDecl->needsOverloadResolutionForMoveAssignment() || + ClassDecl->hasInheritedAssignment()) DeclareImplicitMoveAssignment(ClassDecl); } - if (!ClassDecl->hasUserDeclaredDestructor()) { + if (ClassDecl->needsImplicitDestructor()) { ++ASTContext::NumImplicitDestructors; // If we have a dynamic class, then the destructor may be virtual, so we @@ -7738,7 +7896,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, // function will silently decide not to build a shadow decl, which // will pre-empt further diagnostics. // - // We don't need to do this in C++0x because we do the check once on + // We don't need to do this in C++11 because we do the check once on // the qualifier. // // FIXME: diagnose the following if we care enough: @@ -7796,6 +7954,12 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, for (LookupResult::iterator I = Previous.begin(), E = Previous.end(); I != E; ++I) { NamedDecl *D = (*I)->getUnderlyingDecl(); + // We can have UsingDecls in our Previous results because we use the same + // LookupResult for checking whether the UsingDecl itself is a valid + // redeclaration. + if (isa<UsingDecl>(D)) + continue; + if (IsEquivalentForUsingDecl(Context, D, Target)) { if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(*I)) PrevShadow = Shadow; @@ -7863,12 +8027,21 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, return true; } +/// Determine whether a direct base class is a virtual base class. +static bool isVirtualDirectBase(CXXRecordDecl *Derived, CXXRecordDecl *Base) { + if (!Derived->getNumVBases()) + return false; + for (auto &B : Derived->bases()) + if (B.getType()->getAsCXXRecordDecl() == Base) + return B.isVirtual(); + llvm_unreachable("not a direct base class"); +} + /// Builds a shadow declaration corresponding to a 'using' declaration. UsingShadowDecl *Sema::BuildUsingShadowDecl(Scope *S, UsingDecl *UD, NamedDecl *Orig, UsingShadowDecl *PrevDecl) { - // If we resolved to another shadow declaration, just coalesce them. NamedDecl *Target = Orig; if (isa<UsingShadowDecl>(Target)) { @@ -7876,9 +8049,21 @@ UsingShadowDecl *Sema::BuildUsingShadowDecl(Scope *S, assert(!isa<UsingShadowDecl>(Target) && "nested shadow declaration"); } - UsingShadowDecl *Shadow - = UsingShadowDecl::Create(Context, CurContext, - UD->getLocation(), UD, Target); + NamedDecl *NonTemplateTarget = Target; + if (auto *TargetTD = dyn_cast<TemplateDecl>(Target)) + NonTemplateTarget = TargetTD->getTemplatedDecl(); + + UsingShadowDecl *Shadow; + if (isa<CXXConstructorDecl>(NonTemplateTarget)) { + bool IsVirtualBase = + isVirtualDirectBase(cast<CXXRecordDecl>(CurContext), + UD->getQualifier()->getAsRecordDecl()); + Shadow = ConstructorUsingShadowDecl::Create( + Context, CurContext, UD->getLocation(), UD, Orig, IsVirtualBase); + } else { + Shadow = UsingShadowDecl::Create(Context, CurContext, UD->getLocation(), UD, + Target); + } UD->addShadowDecl(Shadow); Shadow->setAccess(UD->getAccess()); @@ -7980,6 +8165,9 @@ public: if (Candidate.WillReplaceSpecifier() && !Candidate.getCorrectionSpecifier()) return false; + // FIXME: Don't correct to a name that CheckUsingDeclRedeclaration would + // reject. + if (RequireMemberOf) { auto *FoundRecord = dyn_cast<CXXRecordDecl>(ND); if (FoundRecord && FoundRecord->isInjectedClassName()) { @@ -8060,8 +8248,17 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, return nullptr; } + // For an inheriting constructor declaration, the name of the using + // declaration is the name of a constructor in this class, not in the + // base class. + DeclarationNameInfo UsingName = NameInfo; + if (UsingName.getName().getNameKind() == DeclarationName::CXXConstructorName) + if (auto *RD = dyn_cast<CXXRecordDecl>(CurContext)) + UsingName.setName(Context.DeclarationNames.getCXXConstructorName( + Context.getCanonicalType(Context.getRecordType(RD)))); + // Do the redeclaration lookup in the current scope. - LookupResult Previous(*this, NameInfo, LookupUsingDeclName, + LookupResult Previous(*this, UsingName, LookupUsingDeclName, ForRedeclaration); Previous.setHideTags(false); if (S) { @@ -8118,8 +8315,8 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, auto Build = [&](bool Invalid) { UsingDecl *UD = - UsingDecl::Create(Context, CurContext, UsingLoc, QualifierLoc, NameInfo, - HasTypenameKeyword); + UsingDecl::Create(Context, CurContext, UsingLoc, QualifierLoc, + UsingName, HasTypenameKeyword); UD->setAccess(AS); CurContext->addDecl(UD); UD->setInvalidDecl(Invalid); @@ -8174,6 +8371,9 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, // If we corrected to an inheriting constructor, handle it as one. auto *RD = dyn_cast<CXXRecordDecl>(ND); if (RD && RD->isInjectedClassName()) { + // The parent of the injected class name is the class itself. + RD = cast<CXXRecordDecl>(RD->getParent()); + // Fix up the information we'll use to build the using declaration. if (Corrected.WillReplaceSpecifier()) { NestedNameSpecifierLocBuilder Builder; @@ -8182,13 +8382,19 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, QualifierLoc = Builder.getWithLocInContext(Context); } - NameInfo.setName(Context.DeclarationNames.getCXXConstructorName( - Context.getCanonicalType(Context.getRecordType(RD)))); - NameInfo.setNamedTypeInfo(nullptr); + // In this case, the name we introduce is the name of a derived class + // constructor. + auto *CurClass = cast<CXXRecordDecl>(CurContext); + UsingName.setName(Context.DeclarationNames.getCXXConstructorName( + Context.getCanonicalType(Context.getRecordType(CurClass)))); + UsingName.setNamedTypeInfo(nullptr); for (auto *Ctor : LookupConstructors(RD)) R.addDecl(Ctor); + R.resolveKind(); } else { - // FIXME: Pick up all the declarations if we found an overloaded function. + // FIXME: Pick up all the declarations if we found an overloaded + // function. + UsingName.setName(ND->getDeclName()); R.addDecl(ND); } } else { @@ -8221,7 +8427,7 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, } } - // C++0x N2914 [namespace.udecl]p6: + // C++14 [namespace.udecl]p6: // A using-declaration shall not name a namespace. if (R.getAsSingle<NamespaceDecl>()) { Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_namespace) @@ -8229,19 +8435,28 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, return BuildInvalid(); } + // C++14 [namespace.udecl]p7: + // A using-declaration shall not name a scoped enumerator. + if (auto *ED = R.getAsSingle<EnumConstantDecl>()) { + if (cast<EnumDecl>(ED->getDeclContext())->isScoped()) { + Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_scoped_enum) + << SS.getRange(); + return BuildInvalid(); + } + } + UsingDecl *UD = BuildValid(); - // The normal rules do not apply to inheriting constructor declarations. - if (NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName) { + // Some additional rules apply to inheriting constructors. + if (UsingName.getName().getNameKind() == + DeclarationName::CXXConstructorName) { // Suppress access diagnostics; the access check is instead performed at the // point of use for an inheriting constructor. R.suppressDiagnostics(); - CheckInheritingConstructorUsingDecl(UD); - return UD; + if (CheckInheritingConstructorUsingDecl(UD)) + return UD; } - // Otherwise, look up the target name. - for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { UsingShadowDecl *PrevDecl = nullptr; if (!CheckUsingShadowDecl(UD, *I, Previous, PrevDecl)) @@ -8353,8 +8568,10 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc, // If we weren't able to compute a valid scope, it must be a // dependent class scope. - if (!NamedContext || NamedContext->isRecord()) { - auto *RD = dyn_cast_or_null<CXXRecordDecl>(NamedContext); + if (!NamedContext || NamedContext->getRedeclContext()->isRecord()) { + auto *RD = NamedContext + ? cast<CXXRecordDecl>(NamedContext->getRedeclContext()) + : nullptr; if (RD && RequireCompleteDeclContext(const_cast<CXXScopeSpec&>(SS), RD)) RD = nullptr; @@ -8403,6 +8620,20 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc, Diag(UsingLoc, diag::note_using_decl_class_member_workaround) << 2 // reference declaration << FixIt; + } else if (R.getAsSingle<EnumConstantDecl>()) { + // Don't provide a fixit outside C++11 mode; we don't want to suggest + // repeating the type of the enumeration here, and we can't do so if + // the type is anonymous. + FixItHint FixIt; + if (getLangOpts().CPlusPlus11) { + // Convert 'using X::Y;' to 'auto &Y = X::Y;'. + FixIt = FixItHint::CreateReplacement( + UsingLoc, "constexpr auto " + NameInfo.getName().getAsString() + " = "); + } + + Diag(UsingLoc, diag::note_using_decl_class_member_workaround) + << (getLangOpts().CPlusPlus11 ? 4 : 3) // const[expr] variable + << FixIt; } return true; } @@ -8438,7 +8669,7 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc, return true; if (getLangOpts().CPlusPlus11) { - // C++0x [namespace.udecl]p3: + // C++11 [namespace.udecl]p3: // In a using-declaration used as a member-declaration, the // nested-name-specifier shall name a base class of the class // being defined. @@ -8579,6 +8810,10 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S, } TemplateParameterList *TemplateParams = TemplateParamLists[0]; + // Check that we can declare a template here. + if (CheckTemplateDeclScope(S, TemplateParams)) + return nullptr; + // Only consider previous declarations in the same scope. FilterLookupForScope(Previous, CurContext, S, /*ConsiderLinkage*/false, /*ExplicitInstantiationOrSpecialization*/false); @@ -8650,9 +8885,7 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S, NewND = NewTD; } - if (!Redeclaration) - PushOnScopeChains(NewND, S); - + PushOnScopeChains(NewND, S); ActOnDocumentableDecl(NewND); return NewND; } @@ -8796,7 +9029,8 @@ Sema::ComputeDefaultedDefaultCtorExceptionSpec(SourceLocation Loc, } Sema::ImplicitExceptionSpecification -Sema::ComputeInheritingCtorExceptionSpec(CXXConstructorDecl *CD) { +Sema::ComputeInheritingCtorExceptionSpec(SourceLocation Loc, + CXXConstructorDecl *CD) { CXXRecordDecl *ClassDecl = CD->getParent(); // C++ [except.spec]p14: @@ -8805,36 +9039,26 @@ Sema::ComputeInheritingCtorExceptionSpec(CXXConstructorDecl *CD) { if (ClassDecl->isInvalidDecl()) return ExceptSpec; - // Inherited constructor. - const CXXConstructorDecl *InheritedCD = CD->getInheritedConstructor(); - const CXXRecordDecl *InheritedDecl = InheritedCD->getParent(); - // FIXME: Copying or moving the parameters could add extra exceptions to the - // set, as could the default arguments for the inherited constructor. This - // will be addressed when we implement the resolution of core issue 1351. - ExceptSpec.CalledDecl(CD->getLocStart(), InheritedCD); + auto Inherited = CD->getInheritedConstructor(); + InheritedConstructorInfo ICI(*this, Loc, Inherited.getShadowDecl()); - // Direct base-class constructors. - for (const auto &B : ClassDecl->bases()) { - if (B.isVirtual()) // Handled below. - continue; - - if (const RecordType *BaseType = B.getType()->getAs<RecordType>()) { - CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl()); - if (BaseClassDecl == InheritedDecl) + // Direct and virtual base-class constructors. + for (bool VBase : {false, true}) { + for (CXXBaseSpecifier &B : + VBase ? ClassDecl->vbases() : ClassDecl->bases()) { + // Don't visit direct vbases twice. + if (B.isVirtual() != VBase) continue; - CXXConstructorDecl *Constructor = LookupDefaultConstructor(BaseClassDecl); - if (Constructor) - ExceptSpec.CalledDecl(B.getLocStart(), Constructor); - } - } - // Virtual base-class constructors. - for (const auto &B : ClassDecl->vbases()) { - if (const RecordType *BaseType = B.getType()->getAs<RecordType>()) { - CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl()); - if (BaseClassDecl == InheritedDecl) + CXXRecordDecl *BaseClass = B.getType()->getAsCXXRecordDecl(); + if (!BaseClass) continue; - CXXConstructorDecl *Constructor = LookupDefaultConstructor(BaseClassDecl); + + CXXConstructorDecl *Constructor = + ICI.findConstructorForBase(BaseClass, Inherited.getConstructor()) + .first; + if (!Constructor) + Constructor = LookupDefaultConstructor(BaseClass); if (Constructor) ExceptSpec.CalledDecl(B.getLocStart(), Constructor); } @@ -8862,10 +9086,11 @@ namespace { struct DeclaringSpecialMember { Sema &S; Sema::SpecialMemberDecl D; + Sema::ContextRAII SavedContext; bool WasAlreadyBeingDeclared; DeclaringSpecialMember(Sema &S, CXXRecordDecl *RD, Sema::CXXSpecialMember CSM) - : S(S), D(RD, CSM) { + : S(S), D(RD, CSM), SavedContext(S, RD) { WasAlreadyBeingDeclared = !S.SpecialMembersBeingDeclared.insert(D).second; if (WasAlreadyBeingDeclared) // This almost never happens, but if it does, ensure that our cache @@ -8887,6 +9112,21 @@ struct DeclaringSpecialMember { }; } +void Sema::CheckImplicitSpecialMemberDeclaration(Scope *S, FunctionDecl *FD) { + // Look up any existing declarations, but don't trigger declaration of all + // implicit special members with this name. + DeclarationName Name = FD->getDeclName(); + LookupResult R(*this, Name, SourceLocation(), LookupOrdinaryName, + ForRedeclaration); + for (auto *D : FD->getParent()->lookup(Name)) + if (auto *Acceptable = R.getAcceptableDecl(D)) + R.addDecl(Acceptable); + R.resolveKind(); + R.suppressDiagnostics(); + + CheckFunctionDeclaration(S, FD, R, /*IsExplicitSpecialization*/false); +} + CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( CXXRecordDecl *ClassDecl) { // C++ [class.ctor]p5: @@ -8935,13 +9175,16 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( // constructors is easy to compute. DefaultCon->setTrivial(ClassDecl->hasTrivialDefaultConstructor()); - if (ShouldDeleteSpecialMember(DefaultCon, CXXDefaultConstructor)) - SetDeclDeleted(DefaultCon, ClassLoc); - // Note that we have declared this constructor. ++ASTContext::NumImplicitDefaultConstructorsDeclared; - if (Scope *S = getScopeForContext(ClassDecl)) + Scope *S = getScopeForContext(ClassDecl); + CheckImplicitSpecialMemberDeclaration(S, DefaultCon); + + if (ShouldDeleteSpecialMember(DefaultCon, CXXDefaultConstructor)) + SetDeclDeleted(DefaultCon, ClassLoc); + + if (S) PushOnScopeChains(DefaultCon, S, false); ClassDecl->addDecl(DefaultCon); @@ -8993,325 +9236,167 @@ void Sema::ActOnFinishDelayedMemberInitializers(Decl *D) { CheckDelayedMemberExceptionSpecs(); } -namespace { -/// Information on inheriting constructors to declare. -class InheritingConstructorInfo { -public: - InheritingConstructorInfo(Sema &SemaRef, CXXRecordDecl *Derived) - : SemaRef(SemaRef), Derived(Derived) { - // Mark the constructors that we already have in the derived class. - // - // C++11 [class.inhctor]p3: [...] a constructor is implicitly declared [...] - // unless there is a user-declared constructor with the same signature in - // the class where the using-declaration appears. - visitAll(Derived, &InheritingConstructorInfo::noteDeclaredInDerived); - } +/// Find or create the fake constructor we synthesize to model constructing an +/// object of a derived class via a constructor of a base class. +CXXConstructorDecl * +Sema::findInheritingConstructor(SourceLocation Loc, + CXXConstructorDecl *BaseCtor, + ConstructorUsingShadowDecl *Shadow) { + CXXRecordDecl *Derived = Shadow->getParent(); + SourceLocation UsingLoc = Shadow->getLocation(); + + // FIXME: Add a new kind of DeclarationName for an inherited constructor. + // For now we use the name of the base class constructor as a member of the + // derived class to indicate a (fake) inherited constructor name. + DeclarationName Name = BaseCtor->getDeclName(); + + // Check to see if we already have a fake constructor for this inherited + // constructor call. + for (NamedDecl *Ctor : Derived->lookup(Name)) + if (declaresSameEntity(cast<CXXConstructorDecl>(Ctor) + ->getInheritedConstructor() + .getConstructor(), + BaseCtor)) + return cast<CXXConstructorDecl>(Ctor); + + DeclarationNameInfo NameInfo(Name, UsingLoc); + TypeSourceInfo *TInfo = + Context.getTrivialTypeSourceInfo(BaseCtor->getType(), UsingLoc); + FunctionProtoTypeLoc ProtoLoc = + TInfo->getTypeLoc().IgnoreParens().castAs<FunctionProtoTypeLoc>(); + + // Check the inherited constructor is valid and find the list of base classes + // from which it was inherited. + InheritedConstructorInfo ICI(*this, Loc, Shadow); + + bool Constexpr = + BaseCtor->isConstexpr() && + defaultedSpecialMemberIsConstexpr(*this, Derived, CXXDefaultConstructor, + false, BaseCtor, &ICI); + + CXXConstructorDecl *DerivedCtor = CXXConstructorDecl::Create( + Context, Derived, UsingLoc, NameInfo, TInfo->getType(), TInfo, + BaseCtor->isExplicit(), /*Inline=*/true, + /*ImplicitlyDeclared=*/true, Constexpr, + InheritedConstructor(Shadow, BaseCtor)); + if (Shadow->isInvalidDecl()) + DerivedCtor->setInvalidDecl(); + + // Build an unevaluated exception specification for this fake constructor. + const FunctionProtoType *FPT = TInfo->getType()->castAs<FunctionProtoType>(); + FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); + EPI.ExceptionSpec.Type = EST_Unevaluated; + EPI.ExceptionSpec.SourceDecl = DerivedCtor; + DerivedCtor->setType(Context.getFunctionType(FPT->getReturnType(), + FPT->getParamTypes(), EPI)); - void inheritAll(CXXRecordDecl *RD) { - visitAll(RD, &InheritingConstructorInfo::inherit); + // Build the parameter declarations. + SmallVector<ParmVarDecl *, 16> ParamDecls; + for (unsigned I = 0, N = FPT->getNumParams(); I != N; ++I) { + TypeSourceInfo *TInfo = + Context.getTrivialTypeSourceInfo(FPT->getParamType(I), UsingLoc); + ParmVarDecl *PD = ParmVarDecl::Create( + Context, DerivedCtor, UsingLoc, UsingLoc, /*IdentifierInfo=*/nullptr, + FPT->getParamType(I), TInfo, SC_None, /*DefaultArg=*/nullptr); + PD->setScopeInfo(0, I); + PD->setImplicit(); + // Ensure attributes are propagated onto parameters (this matters for + // format, pass_object_size, ...). + mergeDeclAttributes(PD, BaseCtor->getParamDecl(I)); + ParamDecls.push_back(PD); + ProtoLoc.setParam(I, PD); } -private: - /// Information about an inheriting constructor. - struct InheritingConstructor { - InheritingConstructor() - : DeclaredInDerived(false), BaseCtor(nullptr), DerivedCtor(nullptr) {} - - /// If \c true, a constructor with this signature is already declared - /// in the derived class. - bool DeclaredInDerived; - - /// The constructor which is inherited. - const CXXConstructorDecl *BaseCtor; - - /// The derived constructor we declared. - CXXConstructorDecl *DerivedCtor; - }; - - /// Inheriting constructors with a given canonical type. There can be at - /// most one such non-template constructor, and any number of templated - /// constructors. - struct InheritingConstructorsForType { - InheritingConstructor NonTemplate; - SmallVector<std::pair<TemplateParameterList *, InheritingConstructor>, 4> - Templates; - - InheritingConstructor &getEntry(Sema &S, const CXXConstructorDecl *Ctor) { - if (FunctionTemplateDecl *FTD = Ctor->getDescribedFunctionTemplate()) { - TemplateParameterList *ParamList = FTD->getTemplateParameters(); - for (unsigned I = 0, N = Templates.size(); I != N; ++I) - if (S.TemplateParameterListsAreEqual(ParamList, Templates[I].first, - false, S.TPL_TemplateMatch)) - return Templates[I].second; - Templates.push_back(std::make_pair(ParamList, InheritingConstructor())); - return Templates.back().second; - } + // Set up the new constructor. + assert(!BaseCtor->isDeleted() && "should not use deleted constructor"); + DerivedCtor->setAccess(BaseCtor->getAccess()); + DerivedCtor->setParams(ParamDecls); + Derived->addDecl(DerivedCtor); - return NonTemplate; - } - }; + if (ShouldDeleteSpecialMember(DerivedCtor, CXXDefaultConstructor, &ICI)) + SetDeclDeleted(DerivedCtor, UsingLoc); - /// Get or create the inheriting constructor record for a constructor. - InheritingConstructor &getEntry(const CXXConstructorDecl *Ctor, - QualType CtorType) { - return Map[CtorType.getCanonicalType()->castAs<FunctionProtoType>()] - .getEntry(SemaRef, Ctor); - } + return DerivedCtor; +} - typedef void (InheritingConstructorInfo::*VisitFn)(const CXXConstructorDecl*); +void Sema::NoteDeletedInheritingConstructor(CXXConstructorDecl *Ctor) { + InheritedConstructorInfo ICI(*this, Ctor->getLocation(), + Ctor->getInheritedConstructor().getShadowDecl()); + ShouldDeleteSpecialMember(Ctor, CXXDefaultConstructor, &ICI, + /*Diagnose*/true); +} - /// Process all constructors for a class. - void visitAll(const CXXRecordDecl *RD, VisitFn Callback) { - for (const auto *Ctor : RD->ctors()) - (this->*Callback)(Ctor); - for (CXXRecordDecl::specific_decl_iterator<FunctionTemplateDecl> - I(RD->decls_begin()), E(RD->decls_end()); - I != E; ++I) { - const FunctionDecl *FD = (*I)->getTemplatedDecl(); - if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) - (this->*Callback)(CD); - } - } +void Sema::DefineInheritingConstructor(SourceLocation CurrentLocation, + CXXConstructorDecl *Constructor) { + CXXRecordDecl *ClassDecl = Constructor->getParent(); + assert(Constructor->getInheritedConstructor() && + !Constructor->doesThisDeclarationHaveABody() && + !Constructor->isDeleted()); + if (Constructor->isInvalidDecl()) + return; - /// Note that a constructor (or constructor template) was declared in Derived. - void noteDeclaredInDerived(const CXXConstructorDecl *Ctor) { - getEntry(Ctor, Ctor->getType()).DeclaredInDerived = true; - } + ConstructorUsingShadowDecl *Shadow = + Constructor->getInheritedConstructor().getShadowDecl(); + CXXConstructorDecl *InheritedCtor = + Constructor->getInheritedConstructor().getConstructor(); - /// Inherit a single constructor. - void inherit(const CXXConstructorDecl *Ctor) { - const FunctionProtoType *CtorType = - Ctor->getType()->castAs<FunctionProtoType>(); - ArrayRef<QualType> ArgTypes = CtorType->getParamTypes(); - FunctionProtoType::ExtProtoInfo EPI = CtorType->getExtProtoInfo(); + // [class.inhctor.init]p1: + // initialization proceeds as if a defaulted default constructor is used to + // initialize the D object and each base class subobject from which the + // constructor was inherited - SourceLocation UsingLoc = getUsingLoc(Ctor->getParent()); + InheritedConstructorInfo ICI(*this, CurrentLocation, Shadow); + CXXRecordDecl *RD = Shadow->getParent(); + SourceLocation InitLoc = Shadow->getLocation(); - // Core issue (no number yet): the ellipsis is always discarded. - if (EPI.Variadic) { - SemaRef.Diag(UsingLoc, diag::warn_using_decl_constructor_ellipsis); - SemaRef.Diag(Ctor->getLocation(), - diag::note_using_decl_constructor_ellipsis); - EPI.Variadic = false; - } + // Initializations are performed "as if by a defaulted default constructor", + // so enter the appropriate scope. + SynthesizedFunctionScope Scope(*this, Constructor); + DiagnosticErrorTrap Trap(Diags); - // Declare a constructor for each number of parameters. - // - // C++11 [class.inhctor]p1: - // The candidate set of inherited constructors from the class X named in - // the using-declaration consists of [... modulo defects ...] for each - // constructor or constructor template of X, the set of constructors or - // constructor templates that results from omitting any ellipsis parameter - // specification and successively omitting parameters with a default - // argument from the end of the parameter-type-list - unsigned MinParams = minParamsToInherit(Ctor); - unsigned Params = Ctor->getNumParams(); - if (Params >= MinParams) { - do - declareCtor(UsingLoc, Ctor, - SemaRef.Context.getFunctionType( - Ctor->getReturnType(), ArgTypes.slice(0, Params), EPI)); - while (Params > MinParams && - Ctor->getParamDecl(--Params)->hasDefaultArg()); - } - } - - /// Find the using-declaration which specified that we should inherit the - /// constructors of \p Base. - SourceLocation getUsingLoc(const CXXRecordDecl *Base) { - // No fancy lookup required; just look for the base constructor name - // directly within the derived class. - ASTContext &Context = SemaRef.Context; - DeclarationName Name = Context.DeclarationNames.getCXXConstructorName( - Context.getCanonicalType(Context.getRecordType(Base))); - DeclContext::lookup_result Decls = Derived->lookup(Name); - return Decls.empty() ? Derived->getLocation() : Decls[0]->getLocation(); - } - - unsigned minParamsToInherit(const CXXConstructorDecl *Ctor) { - // C++11 [class.inhctor]p3: - // [F]or each constructor template in the candidate set of inherited - // constructors, a constructor template is implicitly declared - if (Ctor->getDescribedFunctionTemplate()) - return 0; - - // For each non-template constructor in the candidate set of inherited - // constructors other than a constructor having no parameters or a - // copy/move constructor having a single parameter, a constructor is - // implicitly declared [...] - if (Ctor->getNumParams() == 0) - return 1; - if (Ctor->isCopyOrMoveConstructor()) - return 2; - - // Per discussion on core reflector, never inherit a constructor which - // would become a default, copy, or move constructor of Derived either. - const ParmVarDecl *PD = Ctor->getParamDecl(0); - const ReferenceType *RT = PD->getType()->getAs<ReferenceType>(); - return (RT && RT->getPointeeCXXRecordDecl() == Derived) ? 2 : 1; - } - - /// Declare a single inheriting constructor, inheriting the specified - /// constructor, with the given type. - void declareCtor(SourceLocation UsingLoc, const CXXConstructorDecl *BaseCtor, - QualType DerivedType) { - InheritingConstructor &Entry = getEntry(BaseCtor, DerivedType); - - // C++11 [class.inhctor]p3: - // ... a constructor is implicitly declared with the same constructor - // characteristics unless there is a user-declared constructor with - // the same signature in the class where the using-declaration appears - if (Entry.DeclaredInDerived) - return; + // Build explicit initializers for all base classes from which the + // constructor was inherited. + SmallVector<CXXCtorInitializer*, 8> Inits; + for (bool VBase : {false, true}) { + for (CXXBaseSpecifier &B : VBase ? RD->vbases() : RD->bases()) { + if (B.isVirtual() != VBase) + continue; - // C++11 [class.inhctor]p7: - // If two using-declarations declare inheriting constructors with the - // same signature, the program is ill-formed - if (Entry.DerivedCtor) { - if (BaseCtor->getParent() != Entry.BaseCtor->getParent()) { - // Only diagnose this once per constructor. - if (Entry.DerivedCtor->isInvalidDecl()) - return; - Entry.DerivedCtor->setInvalidDecl(); - - SemaRef.Diag(UsingLoc, diag::err_using_decl_constructor_conflict); - SemaRef.Diag(BaseCtor->getLocation(), - diag::note_using_decl_constructor_conflict_current_ctor); - SemaRef.Diag(Entry.BaseCtor->getLocation(), - diag::note_using_decl_constructor_conflict_previous_ctor); - SemaRef.Diag(Entry.DerivedCtor->getLocation(), - diag::note_using_decl_constructor_conflict_previous_using); - } else { - // Core issue (no number): if the same inheriting constructor is - // produced by multiple base class constructors from the same base - // class, the inheriting constructor is defined as deleted. - SemaRef.SetDeclDeleted(Entry.DerivedCtor, UsingLoc); - } + auto *BaseRD = B.getType()->getAsCXXRecordDecl(); + if (!BaseRD) + continue; - return; - } + auto BaseCtor = ICI.findConstructorForBase(BaseRD, InheritedCtor); + if (!BaseCtor.first) + continue; - ASTContext &Context = SemaRef.Context; - DeclarationName Name = Context.DeclarationNames.getCXXConstructorName( - Context.getCanonicalType(Context.getRecordType(Derived))); - DeclarationNameInfo NameInfo(Name, UsingLoc); + MarkFunctionReferenced(CurrentLocation, BaseCtor.first); + ExprResult Init = new (Context) CXXInheritedCtorInitExpr( + InitLoc, B.getType(), BaseCtor.first, VBase, BaseCtor.second); - TemplateParameterList *TemplateParams = nullptr; - if (const FunctionTemplateDecl *FTD = - BaseCtor->getDescribedFunctionTemplate()) { - TemplateParams = FTD->getTemplateParameters(); - // We're reusing template parameters from a different DeclContext. This - // is questionable at best, but works out because the template depth in - // both places is guaranteed to be 0. - // FIXME: Rebuild the template parameters in the new context, and - // transform the function type to refer to them. + auto *TInfo = Context.getTrivialTypeSourceInfo(B.getType(), InitLoc); + Inits.push_back(new (Context) CXXCtorInitializer( + Context, TInfo, VBase, InitLoc, Init.get(), InitLoc, + SourceLocation())); } - - // Build type source info pointing at the using-declaration. This is - // required by template instantiation. - TypeSourceInfo *TInfo = - Context.getTrivialTypeSourceInfo(DerivedType, UsingLoc); - FunctionProtoTypeLoc ProtoLoc = - TInfo->getTypeLoc().IgnoreParens().castAs<FunctionProtoTypeLoc>(); - - CXXConstructorDecl *DerivedCtor = CXXConstructorDecl::Create( - Context, Derived, UsingLoc, NameInfo, DerivedType, - TInfo, BaseCtor->isExplicit(), /*Inline=*/true, - /*ImplicitlyDeclared=*/true, /*Constexpr=*/BaseCtor->isConstexpr()); - - // Build an unevaluated exception specification for this constructor. - const FunctionProtoType *FPT = DerivedType->castAs<FunctionProtoType>(); - FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); - EPI.ExceptionSpec.Type = EST_Unevaluated; - EPI.ExceptionSpec.SourceDecl = DerivedCtor; - DerivedCtor->setType(Context.getFunctionType(FPT->getReturnType(), - FPT->getParamTypes(), EPI)); - - // Build the parameter declarations. - SmallVector<ParmVarDecl *, 16> ParamDecls; - for (unsigned I = 0, N = FPT->getNumParams(); I != N; ++I) { - TypeSourceInfo *TInfo = - Context.getTrivialTypeSourceInfo(FPT->getParamType(I), UsingLoc); - ParmVarDecl *PD = ParmVarDecl::Create( - Context, DerivedCtor, UsingLoc, UsingLoc, /*IdentifierInfo=*/nullptr, - FPT->getParamType(I), TInfo, SC_None, /*DefaultArg=*/nullptr); - PD->setScopeInfo(0, I); - PD->setImplicit(); - ParamDecls.push_back(PD); - ProtoLoc.setParam(I, PD); - } - - // Set up the new constructor. - DerivedCtor->setAccess(BaseCtor->getAccess()); - DerivedCtor->setParams(ParamDecls); - DerivedCtor->setInheritedConstructor(BaseCtor); - if (BaseCtor->isDeleted()) - SemaRef.SetDeclDeleted(DerivedCtor, UsingLoc); - - // If this is a constructor template, build the template declaration. - if (TemplateParams) { - FunctionTemplateDecl *DerivedTemplate = - FunctionTemplateDecl::Create(SemaRef.Context, Derived, UsingLoc, Name, - TemplateParams, DerivedCtor); - DerivedTemplate->setAccess(BaseCtor->getAccess()); - DerivedCtor->setDescribedFunctionTemplate(DerivedTemplate); - Derived->addDecl(DerivedTemplate); - } else { - Derived->addDecl(DerivedCtor); - } - - Entry.BaseCtor = BaseCtor; - Entry.DerivedCtor = DerivedCtor; } - Sema &SemaRef; - CXXRecordDecl *Derived; - typedef llvm::DenseMap<const Type *, InheritingConstructorsForType> MapType; - MapType Map; -}; -} - -void Sema::DeclareInheritingConstructors(CXXRecordDecl *ClassDecl) { - // Defer declaring the inheriting constructors until the class is - // instantiated. - if (ClassDecl->isDependentContext()) - return; - - // Find base classes from which we might inherit constructors. - SmallVector<CXXRecordDecl*, 4> InheritedBases; - for (const auto &BaseIt : ClassDecl->bases()) - if (BaseIt.getInheritConstructors()) - InheritedBases.push_back(BaseIt.getType()->getAsCXXRecordDecl()); - - // Go no further if we're not inheriting any constructors. - if (InheritedBases.empty()) - return; - - // Declare the inherited constructors. - InheritingConstructorInfo ICI(*this, ClassDecl); - for (unsigned I = 0, N = InheritedBases.size(); I != N; ++I) - ICI.inheritAll(InheritedBases[I]); -} + // We now proceed as if for a defaulted default constructor, with the relevant + // initializers replaced. -void Sema::DefineInheritingConstructor(SourceLocation CurrentLocation, - CXXConstructorDecl *Constructor) { - CXXRecordDecl *ClassDecl = Constructor->getParent(); - assert(Constructor->getInheritedConstructor() && - !Constructor->doesThisDeclarationHaveABody() && - !Constructor->isDeleted()); - - SynthesizedFunctionScope Scope(*this, Constructor); - DiagnosticErrorTrap Trap(Diags); - if (SetCtorInitializers(Constructor, /*AnyErrors=*/false) || - Trap.hasErrorOccurred()) { - Diag(CurrentLocation, diag::note_inhctor_synthesized_at) - << Context.getTagDeclType(ClassDecl); + bool HadError = SetCtorInitializers(Constructor, /*AnyErrors*/false, Inits); + if (HadError || Trap.hasErrorOccurred()) { + Diag(CurrentLocation, diag::note_inhctor_synthesized_at) << RD; Constructor->setInvalidDecl(); return; } - SourceLocation Loc = Constructor->getLocation(); - Constructor->setBody(new (Context) CompoundStmt(Loc)); + // The exception specification is needed because we are defining the + // function. + ResolveExceptionSpec(CurrentLocation, + Constructor->getType()->castAs<FunctionProtoType>()); + + Constructor->setBody(new (Context) CompoundStmt(InitLoc)); Constructor->markUsed(Context); MarkVTableUsed(CurrentLocation, ClassDecl); @@ -9319,8 +9404,9 @@ void Sema::DefineInheritingConstructor(SourceLocation CurrentLocation, if (ASTMutationListener *L = getASTMutationListener()) { L->CompletedImplicitDefinition(Constructor); } -} + DiagnoseUninitializedFields(*this, Constructor); +} Sema::ImplicitExceptionSpecification Sema::ComputeDefaultedDtorExceptionSpec(CXXMethodDecl *MD) { @@ -9397,20 +9483,21 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) { FunctionProtoType::ExtProtoInfo EPI = getImplicitMethodEPI(*this, Destructor); Destructor->setType(Context.getFunctionType(Context.VoidTy, None, EPI)); - AddOverriddenMethods(ClassDecl, Destructor); - // We don't need to use SpecialMemberIsTrivial here; triviality for // destructors is easy to compute. Destructor->setTrivial(ClassDecl->hasTrivialDestructor()); - if (ShouldDeleteSpecialMember(Destructor, CXXDestructor)) - SetDeclDeleted(Destructor, ClassLoc); - // Note that we have declared this destructor. ++ASTContext::NumImplicitDestructorsDeclared; + Scope *S = getScopeForContext(ClassDecl); + CheckImplicitSpecialMemberDeclaration(S, Destructor); + + if (ShouldDeleteSpecialMember(Destructor, CXXDestructor)) + SetDeclDeleted(Destructor, ClassLoc); + // Introduce this destructor into its scope. - if (Scope *S = getScopeForContext(ClassDecl)) + if (S) PushOnScopeChains(Destructor, S, false); ClassDecl->addDecl(Destructor); @@ -9533,6 +9620,10 @@ void Sema::ActOnFinishCXXNonNestedClass(Decl *D) { if (RD && Context.getTargetInfo().getCXXABI().isMicrosoft()) getDefaultArgExprsForConstructors(*this, RD); + referenceDLLExportedClassMethods(); +} + +void Sema::referenceDLLExportedClassMethods() { if (!DelayedDllExportClasses.empty()) { // Calling ReferenceDllExportedMethods might cause the current function to // be called again, so use a local copy of DelayedDllExportClasses. @@ -9969,10 +10060,10 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T, SizeType, VK_LValue, OK_Ordinary, Loc); // Construct the loop that copies all elements of this array. - return S.ActOnForStmt(Loc, Loc, InitStmt, - S.MakeFullExpr(Comparison), - nullptr, S.MakeFullDiscardedValueExpr(Increment), - Loc, Copy.get()); + return S.ActOnForStmt( + Loc, Loc, InitStmt, + S.ActOnCondition(nullptr, Loc, Comparison, Sema::ConditionKind::Boolean), + S.MakeFullDiscardedValueExpr(Increment), Loc, Copy.get()); } static StmtResult @@ -10107,20 +10198,21 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { nullptr); CopyAssignment->setParams(FromParam); - AddOverriddenMethods(ClassDecl, CopyAssignment); - CopyAssignment->setTrivial( ClassDecl->needsOverloadResolutionForCopyAssignment() ? SpecialMemberIsTrivial(CopyAssignment, CXXCopyAssignment) : ClassDecl->hasTrivialCopyAssignment()); - if (ShouldDeleteSpecialMember(CopyAssignment, CXXCopyAssignment)) - SetDeclDeleted(CopyAssignment, ClassLoc); - // Note that we have added this copy-assignment operator. ++ASTContext::NumImplicitCopyAssignmentOperatorsDeclared; - if (Scope *S = getScopeForContext(ClassDecl)) + Scope *S = getScopeForContext(ClassDecl); + CheckImplicitSpecialMemberDeclaration(S, CopyAssignment); + + if (ShouldDeleteSpecialMember(CopyAssignment, CXXCopyAssignment)) + SetDeclDeleted(CopyAssignment, ClassLoc); + + if (S) PushOnScopeChains(CopyAssignment, S, false); ClassDecl->addDecl(CopyAssignment); @@ -10498,22 +10590,23 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) { nullptr); MoveAssignment->setParams(FromParam); - AddOverriddenMethods(ClassDecl, MoveAssignment); - MoveAssignment->setTrivial( ClassDecl->needsOverloadResolutionForMoveAssignment() ? SpecialMemberIsTrivial(MoveAssignment, CXXMoveAssignment) : ClassDecl->hasTrivialMoveAssignment()); + // Note that we have added this copy-assignment operator. + ++ASTContext::NumImplicitMoveAssignmentOperatorsDeclared; + + Scope *S = getScopeForContext(ClassDecl); + CheckImplicitSpecialMemberDeclaration(S, MoveAssignment); + if (ShouldDeleteSpecialMember(MoveAssignment, CXXMoveAssignment)) { ClassDecl->setImplicitMoveAssignmentIsDeleted(); SetDeclDeleted(MoveAssignment, ClassLoc); } - // Note that we have added this copy-assignment operator. - ++ASTContext::NumImplicitMoveAssignmentOperatorsDeclared; - - if (Scope *S = getScopeForContext(ClassDecl)) + if (S) PushOnScopeChains(MoveAssignment, S, false); ClassDecl->addDecl(MoveAssignment); @@ -10939,13 +11032,16 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( ? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor) : ClassDecl->hasTrivialCopyConstructor()); - if (ShouldDeleteSpecialMember(CopyConstructor, CXXCopyConstructor)) - SetDeclDeleted(CopyConstructor, ClassLoc); - // Note that we have declared this constructor. ++ASTContext::NumImplicitCopyConstructorsDeclared; - if (Scope *S = getScopeForContext(ClassDecl)) + Scope *S = getScopeForContext(ClassDecl); + CheckImplicitSpecialMemberDeclaration(S, CopyConstructor); + + if (ShouldDeleteSpecialMember(CopyConstructor, CXXCopyConstructor)) + SetDeclDeleted(CopyConstructor, ClassLoc); + + if (S) PushOnScopeChains(CopyConstructor, S, false); ClassDecl->addDecl(CopyConstructor); @@ -11116,15 +11212,18 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor( ? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor) : ClassDecl->hasTrivialMoveConstructor()); + // Note that we have declared this constructor. + ++ASTContext::NumImplicitMoveConstructorsDeclared; + + Scope *S = getScopeForContext(ClassDecl); + CheckImplicitSpecialMemberDeclaration(S, MoveConstructor); + if (ShouldDeleteSpecialMember(MoveConstructor, CXXMoveConstructor)) { ClassDecl->setImplicitMoveConstructorIsDeleted(); SetDeclDeleted(MoveConstructor, ClassLoc); } - // Note that we have declared this constructor. - ++ASTContext::NumImplicitMoveConstructorsDeclared; - - if (Scope *S = getScopeForContext(ClassDecl)) + if (S) PushOnScopeChains(MoveConstructor, S, false); ClassDecl->addDecl(MoveConstructor); @@ -11329,6 +11428,7 @@ static bool hasOneRealArgument(MultiExprArg Args) { ExprResult Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, + NamedDecl *FoundDecl, CXXConstructorDecl *Constructor, MultiExprArg ExprArgs, bool HadMultipleCandidates, @@ -11349,24 +11449,51 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, // with the same cv-unqualified type, the copy/move operation // can be omitted by constructing the temporary object // directly into the target of the omitted copy/move - if (ConstructKind == CXXConstructExpr::CK_Complete && + if (ConstructKind == CXXConstructExpr::CK_Complete && Constructor && Constructor->isCopyOrMoveConstructor() && hasOneRealArgument(ExprArgs)) { Expr *SubExpr = ExprArgs[0]; - Elidable = SubExpr->isTemporaryObject(Context, Constructor->getParent()); + Elidable = SubExpr->isTemporaryObject( + Context, cast<CXXRecordDecl>(FoundDecl->getDeclContext())); } - return BuildCXXConstructExpr(ConstructLoc, DeclInitType, Constructor, + return BuildCXXConstructExpr(ConstructLoc, DeclInitType, + FoundDecl, Constructor, Elidable, ExprArgs, HadMultipleCandidates, IsListInitialization, IsStdInitListInitialization, RequiresZeroInit, ConstructKind, ParenRange); } +ExprResult +Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, + NamedDecl *FoundDecl, + CXXConstructorDecl *Constructor, + bool Elidable, + MultiExprArg ExprArgs, + bool HadMultipleCandidates, + bool IsListInitialization, + bool IsStdInitListInitialization, + bool RequiresZeroInit, + unsigned ConstructKind, + SourceRange ParenRange) { + if (auto *Shadow = dyn_cast<ConstructorUsingShadowDecl>(FoundDecl)) { + Constructor = findInheritingConstructor(ConstructLoc, Constructor, Shadow); + if (DiagnoseUseOfDecl(Constructor, ConstructLoc)) + return ExprError(); + } + + return BuildCXXConstructExpr( + ConstructLoc, DeclInitType, Constructor, Elidable, ExprArgs, + HadMultipleCandidates, IsListInitialization, IsStdInitListInitialization, + RequiresZeroInit, ConstructKind, ParenRange); +} + /// BuildCXXConstructExpr - Creates a complete call to a constructor, /// including handling of its default argument expressions. ExprResult Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, - CXXConstructorDecl *Constructor, bool Elidable, + CXXConstructorDecl *Constructor, + bool Elidable, MultiExprArg ExprArgs, bool HadMultipleCandidates, bool IsListInitialization, @@ -11374,11 +11501,16 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, bool RequiresZeroInit, unsigned ConstructKind, SourceRange ParenRange) { + assert(declaresSameEntity( + Constructor->getParent(), + DeclInitType->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) && + "given constructor for wrong type"); MarkFunctionReferenced(ConstructLoc, Constructor); + return CXXConstructExpr::Create( - Context, DeclInitType, ConstructLoc, Constructor, Elidable, ExprArgs, - HadMultipleCandidates, IsListInitialization, IsStdInitListInitialization, - RequiresZeroInit, + Context, DeclInitType, ConstructLoc, Constructor, Elidable, + ExprArgs, HadMultipleCandidates, IsListInitialization, + IsStdInitListInitialization, RequiresZeroInit, static_cast<CXXConstructExpr::ConstructionKind>(ConstructKind), ParenRange); } @@ -11398,8 +11530,19 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { CXXRecordDecl *ClassPattern = ParentRD->getTemplateInstantiationPattern(); DeclContext::lookup_result Lookup = ClassPattern->lookup(Field->getDeclName()); - assert(Lookup.size() == 1); - FieldDecl *Pattern = cast<FieldDecl>(Lookup[0]); + + // Lookup can return at most two results: the pattern for the field, or the + // injected class name of the parent record. No other member can have the + // same name as the field. + assert(!Lookup.empty() && Lookup.size() <= 2 && + "more than two lookup results for field name"); + FieldDecl *Pattern = dyn_cast<FieldDecl>(Lookup[0]); + if (!Pattern) { + assert(isa<CXXRecordDecl>(Lookup[0]) && + "cannot have other non-field member with same name"); + Pattern = cast<FieldDecl>(Lookup[1]); + } + if (InstantiateInClassInitializer(Loc, Field, Pattern, getTemplateInstantiationArgs(Field))) return ExprError(); @@ -11660,7 +11803,7 @@ bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) { diag::err_operator_overload_static) << FnDecl->getDeclName(); } else { bool ClassOrEnumParam = false; - for (auto Param : FnDecl->params()) { + for (auto Param : FnDecl->parameters()) { QualType ParamType = Param->getType().getNonReferenceType(); if (ParamType->isDependentType() || ParamType->isRecordType() || ParamType->isEnumeralType()) { @@ -11682,7 +11825,7 @@ bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) { // Only the function-call operator allows default arguments // (C++ [over.call]p1). if (Op != OO_Call) { - for (auto Param : FnDecl->params()) { + for (auto Param : FnDecl->parameters()) { if (Param->hasDefaultArg()) return Diag(Param->getLocation(), diag::err_operator_overload_default_arg) @@ -11765,6 +11908,49 @@ bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) { return false; } +static bool +checkLiteralOperatorTemplateParameterList(Sema &SemaRef, + FunctionTemplateDecl *TpDecl) { + TemplateParameterList *TemplateParams = TpDecl->getTemplateParameters(); + + // Must have one or two template parameters. + if (TemplateParams->size() == 1) { + NonTypeTemplateParmDecl *PmDecl = + dyn_cast<NonTypeTemplateParmDecl>(TemplateParams->getParam(0)); + + // The template parameter must be a char parameter pack. + if (PmDecl && PmDecl->isTemplateParameterPack() && + SemaRef.Context.hasSameType(PmDecl->getType(), SemaRef.Context.CharTy)) + return false; + + } else if (TemplateParams->size() == 2) { + TemplateTypeParmDecl *PmType = + dyn_cast<TemplateTypeParmDecl>(TemplateParams->getParam(0)); + NonTypeTemplateParmDecl *PmArgs = + dyn_cast<NonTypeTemplateParmDecl>(TemplateParams->getParam(1)); + + // The second template parameter must be a parameter pack with the + // first template parameter as its type. + if (PmType && PmArgs && !PmType->isTemplateParameterPack() && + PmArgs->isTemplateParameterPack()) { + const TemplateTypeParmType *TArgs = + PmArgs->getType()->getAs<TemplateTypeParmType>(); + if (TArgs && TArgs->getDepth() == PmType->getDepth() && + TArgs->getIndex() == PmType->getIndex()) { + if (SemaRef.ActiveTemplateInstantiations.empty()) + SemaRef.Diag(TpDecl->getLocation(), + diag::ext_string_literal_operator_template); + return false; + } + } + } + + SemaRef.Diag(TpDecl->getTemplateParameters()->getSourceRange().getBegin(), + diag::err_literal_operator_template) + << TpDecl->getTemplateParameters()->getSourceRange(); + return true; +} + /// CheckLiteralOperatorDeclaration - Check whether the declaration /// of this literal operator function is well-formed. If so, returns /// false; otherwise, emits appropriate diagnostics and returns true. @@ -11780,10 +11966,9 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) { 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(); @@ -11792,104 +11977,120 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) { // template <class T, T...> type operator "" name() are the only valid // template signatures, and the only valid signatures with no parameters. if (TpDecl) { - if (FnDecl->param_size() == 0) { - // Must have one or two template parameters - TemplateParameterList *Params = TpDecl->getTemplateParameters(); - if (Params->size() == 1) { - NonTypeTemplateParmDecl *PmDecl = - dyn_cast<NonTypeTemplateParmDecl>(Params->getParam(0)); - - // The template parameter must be a char parameter pack. - if (PmDecl && PmDecl->isTemplateParameterPack() && - Context.hasSameType(PmDecl->getType(), Context.CharTy)) - Valid = true; - } else if (Params->size() == 2) { - TemplateTypeParmDecl *PmType = - dyn_cast<TemplateTypeParmDecl>(Params->getParam(0)); - NonTypeTemplateParmDecl *PmArgs = - dyn_cast<NonTypeTemplateParmDecl>(Params->getParam(1)); - - // The second template parameter must be a parameter pack with the - // first template parameter as its type. - if (PmType && PmArgs && - !PmType->isTemplateParameterPack() && - PmArgs->isTemplateParameterPack()) { - const TemplateTypeParmType *TArgs = - PmArgs->getType()->getAs<TemplateTypeParmType>(); - if (TArgs && TArgs->getDepth() == PmType->getDepth() && - TArgs->getIndex() == PmType->getIndex()) { - Valid = true; - if (ActiveTemplateInstantiations.empty()) - Diag(FnDecl->getLocation(), - diag::ext_string_literal_operator_template); - } - } + if (FnDecl->param_size() != 0) { + Diag(FnDecl->getLocation(), + diag::err_literal_operator_template_with_params); + return true; + } + + if (checkLiteralOperatorTemplateParameterList(*this, TpDecl)) + return true; + + } else if (FnDecl->param_size() == 1) { + const ParmVarDecl *Param = FnDecl->getParamDecl(0); + + QualType ParamType = Param->getType().getUnqualifiedType(); + + // Only unsigned long long int, long double, any character type, and const + // char * are allowed as the only parameters. + if (ParamType->isSpecificBuiltinType(BuiltinType::ULongLong) || + ParamType->isSpecificBuiltinType(BuiltinType::LongDouble) || + Context.hasSameType(ParamType, Context.CharTy) || + Context.hasSameType(ParamType, Context.WideCharTy) || + Context.hasSameType(ParamType, Context.Char16Ty) || + Context.hasSameType(ParamType, Context.Char32Ty)) { + } else if (const PointerType *Ptr = ParamType->getAs<PointerType>()) { + QualType InnerType = Ptr->getPointeeType(); + + // Pointer parameter must be a const char *. + if (!(Context.hasSameType(InnerType.getUnqualifiedType(), + Context.CharTy) && + InnerType.isConstQualified() && !InnerType.isVolatileQualified())) { + Diag(Param->getSourceRange().getBegin(), + diag::err_literal_operator_param) + << ParamType << "'const char *'" << Param->getSourceRange(); + return true; } + + } else if (ParamType->isRealFloatingType()) { + Diag(Param->getSourceRange().getBegin(), diag::err_literal_operator_param) + << ParamType << Context.LongDoubleTy << Param->getSourceRange(); + return true; + + } else if (ParamType->isIntegerType()) { + Diag(Param->getSourceRange().getBegin(), diag::err_literal_operator_param) + << ParamType << Context.UnsignedLongLongTy << Param->getSourceRange(); + return true; + + } else { + Diag(Param->getSourceRange().getBegin(), + diag::err_literal_operator_invalid_param) + << ParamType << Param->getSourceRange(); + return true; } - } else if (FnDecl->param_size()) { - // Check the first parameter + + } else if (FnDecl->param_size() == 2) { FunctionDecl::param_iterator Param = FnDecl->param_begin(); - QualType T = (*Param)->getType().getUnqualifiedType(); - - // unsigned long long int, long double, and any character type are allowed - // as the only parameters. - if (Context.hasSameType(T, Context.UnsignedLongLongTy) || - Context.hasSameType(T, Context.LongDoubleTy) || - Context.hasSameType(T, Context.CharTy) || - Context.hasSameType(T, Context.WideCharTy) || - Context.hasSameType(T, Context.Char16Ty) || - Context.hasSameType(T, Context.Char32Ty)) { - if (++Param == FnDecl->param_end()) - Valid = true; - goto FinishedParams; - } - - // Otherwise it must be a pointer to const; let's strip those qualifiers. - const PointerType *PT = T->getAs<PointerType>(); - if (!PT) - goto FinishedParams; - T = PT->getPointeeType(); - if (!T.isConstQualified() || T.isVolatileQualified()) - goto FinishedParams; - T = T.getUnqualifiedType(); - - // Move on to the second parameter; - ++Param; + // First, verify that the first parameter is correct. - // If there is no second parameter, the first must be a const char * - if (Param == FnDecl->param_end()) { - if (Context.hasSameType(T, Context.CharTy)) - Valid = true; - goto FinishedParams; + QualType FirstParamType = (*Param)->getType().getUnqualifiedType(); + + // Two parameter function must have a pointer to const as a + // first parameter; let's strip those qualifiers. + const PointerType *PT = FirstParamType->getAs<PointerType>(); + + if (!PT) { + Diag((*Param)->getSourceRange().getBegin(), + diag::err_literal_operator_param) + << FirstParamType << "'const char *'" << (*Param)->getSourceRange(); + return true; + } + + QualType PointeeType = PT->getPointeeType(); + // First parameter must be const + if (!PointeeType.isConstQualified() || PointeeType.isVolatileQualified()) { + Diag((*Param)->getSourceRange().getBegin(), + diag::err_literal_operator_param) + << FirstParamType << "'const char *'" << (*Param)->getSourceRange(); + return true; } - // const char *, const wchar_t*, const char16_t*, and const char32_t* + QualType InnerType = PointeeType.getUnqualifiedType(); + // Only const char *, const wchar_t*, const char16_t*, and const char32_t* // are allowed as the first parameter to a two-parameter function - if (!(Context.hasSameType(T, Context.CharTy) || - Context.hasSameType(T, Context.WideCharTy) || - Context.hasSameType(T, Context.Char16Ty) || - Context.hasSameType(T, Context.Char32Ty))) - goto FinishedParams; - - // The second and final parameter must be an std::size_t - T = (*Param)->getType().getUnqualifiedType(); - if (Context.hasSameType(T, Context.getSizeType()) && - ++Param == FnDecl->param_end()) - Valid = true; - } - - // FIXME: This diagnostic is absolutely terrible. -FinishedParams: - if (!Valid) { - Diag(FnDecl->getLocation(), diag::err_literal_operator_params) - << FnDecl->getDeclName(); + if (!(Context.hasSameType(InnerType, Context.CharTy) || + Context.hasSameType(InnerType, Context.WideCharTy) || + Context.hasSameType(InnerType, Context.Char16Ty) || + Context.hasSameType(InnerType, Context.Char32Ty))) { + Diag((*Param)->getSourceRange().getBegin(), + diag::err_literal_operator_param) + << FirstParamType << "'const char *'" << (*Param)->getSourceRange(); + return true; + } + + // Move on to the second and final parameter. + ++Param; + + // The second parameter must be a std::size_t. + QualType SecondParamType = (*Param)->getType().getUnqualifiedType(); + if (!Context.hasSameType(SecondParamType, Context.getSizeType())) { + Diag((*Param)->getSourceRange().getBegin(), + diag::err_literal_operator_param) + << SecondParamType << Context.getSizeType() + << (*Param)->getSourceRange(); + return true; + } + } else { + Diag(FnDecl->getLocation(), diag::err_literal_operator_bad_param_count); return true; } + // Parameters are good. + // A parameter-declaration-clause containing a default argument is not // equivalent to any of the permitted forms. - for (auto Param : FnDecl->params()) { + for (auto Param : FnDecl->parameters()) { if (Param->hasDefaultArg()) { Diag(Param->getDefaultArgRange().getBegin(), diag::err_literal_operator_default_argument) @@ -12003,6 +12204,11 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, Invalid = true; } + if (ExDeclType->isVariablyModifiedType()) { + Diag(Loc, diag::err_catch_variably_modified) << ExDeclType; + Invalid = true; + } + QualType BaseType = ExDeclType; int Mode = 0; // 0 for direct type, 1 for pointer, 2 for reference unsigned DK = diag::err_catch_incomplete; @@ -12468,10 +12674,9 @@ Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, // friend a member of an arbitrary specialization of your template). Decl *D; - if (unsigned NumTempParamLists = TempParams.size()) + if (!TempParams.empty()) D = FriendTemplateDecl::Create(Context, CurContext, Loc, - NumTempParamLists, - TempParams.data(), + TempParams, TSI, DS.getFriendSpecLoc()); else @@ -12894,44 +13099,20 @@ void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) { // the record is complete. const FunctionDecl *Primary = MD; if (const FunctionDecl *Pattern = MD->getTemplateInstantiationPattern()) - // Find the uninstantiated declaration that actually had the '= default' - // on it. - Pattern->isDefined(Primary); + // Ask the template instantiation pattern that actually had the + // '= default' on it. + Primary = Pattern; // If the method was defaulted on its first declaration, we will have // already performed the checking in CheckCompletedCXXClass. Such a // declaration doesn't trigger an implicit definition. - if (Primary == Primary->getCanonicalDecl()) + if (Primary->getCanonicalDecl()->isDefaulted()) return; CheckExplicitlyDefaultedSpecialMember(MD); - if (MD->isInvalidDecl()) - return; - - switch (Member) { - case CXXDefaultConstructor: - DefineImplicitDefaultConstructor(DefaultLoc, - cast<CXXConstructorDecl>(MD)); - break; - case CXXCopyConstructor: - DefineImplicitCopyConstructor(DefaultLoc, cast<CXXConstructorDecl>(MD)); - break; - case CXXCopyAssignment: - DefineImplicitCopyAssignment(DefaultLoc, MD); - break; - case CXXDestructor: - DefineImplicitDestructor(DefaultLoc, cast<CXXDestructorDecl>(MD)); - break; - case CXXMoveConstructor: - DefineImplicitMoveConstructor(DefaultLoc, cast<CXXConstructorDecl>(MD)); - break; - case CXXMoveAssignment: - DefineImplicitMoveAssignment(DefaultLoc, MD); - break; - case CXXInvalid: - llvm_unreachable("Invalid special member."); - } + if (!MD->isInvalidDecl()) + DefineImplicitSpecialMember(*this, MD, DefaultLoc); } else { Diag(DefaultLoc, diag::err_default_special_members); } @@ -13020,19 +13201,20 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, return true; } - // C++ [class.virtual]p6: - // If the return type of D::f differs from the return type of B::f, the - // class type in the return type of D::f shall be complete at the point of - // declaration of D::f or shall be the class type D. - if (const RecordType *RT = NewClassTy->getAs<RecordType>()) { - if (!RT->isBeingDefined() && - RequireCompleteType(New->getLocation(), NewClassTy, - diag::err_covariant_return_incomplete, - New->getDeclName())) - return true; - } - if (!Context.hasSameUnqualifiedType(NewClassTy, OldClassTy)) { + // C++14 [class.virtual]p8: + // If the class type in the covariant return type of D::f differs from + // that of B::f, the class type in the return type of D::f shall be + // complete at the point of declaration of D::f or shall be the class + // type D. + if (const RecordType *RT = NewClassTy->getAs<RecordType>()) { + if (!RT->isBeingDefined() && + RequireCompleteType(New->getLocation(), NewClassTy, + diag::err_covariant_return_incomplete, + New->getDeclName())) + return true; + } + // Check if the new class derives from the old class. if (!IsDerivedFrom(New->getLocation(), NewClassTy, OldClassTy)) { Diag(New->getLocation(), diag::err_covariant_return_not_derived) @@ -13069,7 +13251,7 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, Diag(Old->getLocation(), diag::note_overridden_virtual_function) << Old->getReturnTypeSourceRange(); return true; - }; + } // The new class type must have the same or less qualifiers as the old type. @@ -13081,7 +13263,7 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, Diag(Old->getLocation(), diag::note_overridden_virtual_function) << Old->getReturnTypeSourceRange(); return true; - }; + } return false; } @@ -13240,14 +13422,19 @@ void Sema::MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class, // checks (i.e. operator delete() lookup) when the vtable is marked used, as // the deleting destructor is emitted with the vtable, not with the // destructor definition as in the Itanium ABI. - // If it has a definition, we do the check at that point instead. - if (Context.getTargetInfo().getCXXABI().isMicrosoft() && - Class->hasUserDeclaredDestructor() && - !Class->getDestructor()->isDefined() && - !Class->getDestructor()->isDeleted()) { + if (Context.getTargetInfo().getCXXABI().isMicrosoft()) { CXXDestructorDecl *DD = Class->getDestructor(); - ContextRAII SavedContext(*this, DD); - CheckDestructor(DD); + if (DD && DD->isVirtual() && !DD->isDeleted()) { + if (Class->hasUserDeclaredDestructor() && !DD->isDefined()) { + // If this is an out-of-line declaration, marking it referenced will + // not do anything. Manually call CheckDestructor to look up operator + // delete(). + ContextRAII SavedContext(*this, DD); + CheckDestructor(DD); + } else { + MarkFunctionReferenced(Loc, Class->getDestructor()); + } + } } } @@ -13785,6 +13972,9 @@ MSPropertyDecl *Sema::HandleMSProperty(Scope *S, RecordDecl *Record, DiagnoseFunctionSpecifiers(D.getDeclSpec()); + if (D.getDeclSpec().isInlineSpecified()) + Diag(D.getDeclSpec().getInlineSpecLoc(), diag::err_inline_non_function) + << getLangOpts().CPlusPlus1z; if (DeclSpec::TSCS TSCS = D.getDeclSpec().getThreadStorageClassSpec()) Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(), diag::err_invalid_thread) |