diff options
Diffstat (limited to 'lib/Sema/SemaDeclCXX.cpp')
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 1150 |
1 files changed, 771 insertions, 379 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index aa26b37f444d..4cf3abdf5745 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -17,6 +17,7 @@ #include "clang/AST/ASTMutationListener.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/CharUnits.h" +#include "clang/AST/ComparisonCategories.h" #include "clang/AST/EvaluatedExprVisitor.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/RecordLayout.h" @@ -170,43 +171,40 @@ Sema::ImplicitExceptionSpecification::CalledDecl(SourceLocation CallLoc, if (EST == EST_None && Method->hasAttr<NoThrowAttr>()) EST = EST_BasicNoexcept; - switch(EST) { + switch (EST) { + case EST_Unparsed: + case EST_Uninstantiated: + case EST_Unevaluated: + llvm_unreachable("should not see unresolved exception specs here"); + // If this function can throw any exceptions, make a note of that. case EST_MSAny: case EST_None: + // FIXME: Whichever we see last of MSAny and None determines our result. + // We should make a consistent, order-independent choice here. ClearExceptions(); ComputedEST = EST; return; + case EST_NoexceptFalse: + ClearExceptions(); + ComputedEST = EST_None; + return; // FIXME: If the call to this decl is using any of its default arguments, we // need to search them for potentially-throwing calls. // If this function has a basic noexcept, it doesn't affect the outcome. case EST_BasicNoexcept: + case EST_NoexceptTrue: return; - // If we're still at noexcept(true) and there's a nothrow() callee, + // If we're still at noexcept(true) and there's a throw() callee, // change to that specification. case EST_DynamicNone: if (ComputedEST == EST_BasicNoexcept) ComputedEST = EST_DynamicNone; return; - // Check out noexcept specs. - case EST_ComputedNoexcept: - { - FunctionProtoType::NoexceptResult NR = - Proto->getNoexceptSpec(Self->Context); - assert(NR != FunctionProtoType::NR_NoNoexcept && - "Must have noexcept result for EST_ComputedNoexcept."); - assert(NR != FunctionProtoType::NR_Dependent && - "Should not generate implicit declarations for dependent cases, " - "and don't know how to handle them anyway."); - // noexcept(false) -> no spec on the new function - if (NR == FunctionProtoType::NR_Throw) { - ClearExceptions(); - ComputedEST = EST_None; - } - // noexcept(true) won't change anything either. - return; - } - default: + case EST_DependentNoexcept: + llvm_unreachable( + "should not generate implicit declarations for dependent cases"); + case EST_Dynamic: break; } assert(EST == EST_Dynamic && "EST case not considered earlier."); @@ -712,7 +710,7 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D, Diag(Decomp.getLSquareLoc(), !getLangOpts().CPlusPlus17 ? diag::ext_decomp_decl - : D.getContext() == Declarator::ConditionContext + : D.getContext() == DeclaratorContext::ConditionContext ? diag::ext_decomp_decl_cond : diag::warn_cxx14_compat_decomp_decl) << Decomp.getSourceRange(); @@ -1459,7 +1457,7 @@ void Sema::CheckCompleteDecompositionDeclaration(DecompositionDecl *DD) { DD->setInvalidDecl(); } -/// \brief Merge the exception specifications of two variable declarations. +/// Merge the exception specifications of two variable declarations. /// /// This is called when there's a redeclaration of a VarDecl. The function /// checks if the redeclaration might have an exception specification and @@ -1575,7 +1573,7 @@ static bool CheckConstexprParameterTypes(Sema &SemaRef, return true; } -/// \brief Get diagnostic %select index for tag kind for +/// Get diagnostic %select index for tag kind for /// record diagnostic message. /// WARNING: Indexes apply to particular diagnostics only! /// @@ -2061,27 +2059,39 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) { return true; } +/// Get the class that is directly named by the current context. This is the +/// class for which an unqualified-id in this scope could name a constructor +/// or destructor. +/// +/// If the scope specifier denotes a class, this will be that class. +/// If the scope specifier is empty, this will be the class whose +/// member-specification we are currently within. Otherwise, there +/// is no such class. +CXXRecordDecl *Sema::getCurrentClass(Scope *, const CXXScopeSpec *SS) { + assert(getLangOpts().CPlusPlus && "No class names in C!"); + + if (SS && SS->isInvalid()) + return nullptr; + + if (SS && SS->isNotEmpty()) { + DeclContext *DC = computeDeclContext(*SS, true); + return dyn_cast_or_null<CXXRecordDecl>(DC); + } + + return dyn_cast_or_null<CXXRecordDecl>(CurContext); +} + /// isCurrentClassName - Determine whether the identifier II is the /// name of the class type currently being defined. In the case of /// nested classes, this will only return true if II is the name of /// the innermost class. -bool Sema::isCurrentClassName(const IdentifierInfo &II, Scope *, +bool Sema::isCurrentClassName(const IdentifierInfo &II, Scope *S, const CXXScopeSpec *SS) { - assert(getLangOpts().CPlusPlus && "No class names in C!"); - - CXXRecordDecl *CurDecl; - if (SS && SS->isSet() && !SS->isInvalid()) { - DeclContext *DC = computeDeclContext(*SS, true); - CurDecl = dyn_cast_or_null<CXXRecordDecl>(DC); - } else - CurDecl = dyn_cast_or_null<CXXRecordDecl>(CurContext); - - if (CurDecl && CurDecl->getIdentifier()) - return &II == CurDecl->getIdentifier(); - return false; + CXXRecordDecl *CurDecl = getCurrentClass(S, SS); + return CurDecl && &II == CurDecl->getIdentifier(); } -/// \brief Determine whether the identifier II is a typo for the name of +/// Determine whether the identifier II is a typo for the name of /// the class type currently being defined. If so, update it to the identifier /// that should have been used. bool Sema::isCurrentClassNameTypo(IdentifierInfo *&II, const CXXScopeSpec *SS) { @@ -2107,7 +2117,7 @@ bool Sema::isCurrentClassNameTypo(IdentifierInfo *&II, const CXXScopeSpec *SS) { return false; } -/// \brief Determine whether the given class is a base class of the given +/// Determine whether the given class is a base class of the given /// class, including looking at dependent bases. static bool findCircularInheritance(const CXXRecordDecl *Class, const CXXRecordDecl *Current) { @@ -2139,7 +2149,7 @@ static bool findCircularInheritance(const CXXRecordDecl *Class, return false; } -/// \brief Check the validity of a C++ base class specifier. +/// Check the validity of a C++ base class specifier. /// /// \returns a new CXXBaseSpecifier if well-formed, emits diagnostics /// and returns NULL otherwise. @@ -2233,6 +2243,19 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, CXXRecordDecl *CXXBaseDecl = cast<CXXRecordDecl>(BaseDecl); assert(CXXBaseDecl && "Base type is not a C++ type"); + // Microsoft docs say: + // "If a base-class has a code_seg attribute, derived classes must have the + // same attribute." + const auto *BaseCSA = CXXBaseDecl->getAttr<CodeSegAttr>(); + const auto *DerivedCSA = Class->getAttr<CodeSegAttr>(); + if ((DerivedCSA || BaseCSA) && + (!BaseCSA || !DerivedCSA || BaseCSA->getName() != DerivedCSA->getName())) { + Diag(Class->getLocation(), diag::err_mismatched_code_seg_base); + Diag(CXXBaseDecl->getLocation(), diag::note_base_class_specified_here) + << CXXBaseDecl; + return nullptr; + } + // A class which contains a flexible array member is not suitable for use as a // base class: // - If the layout determines that a base comes before another base, @@ -2290,18 +2313,13 @@ Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange, // We do not support any C++11 attributes on base-specifiers yet. // Diagnose any attributes we see. - if (!Attributes.empty()) { - for (AttributeList *Attr = Attributes.getList(); Attr; - Attr = Attr->getNext()) { - if (Attr->isInvalid() || - Attr->getKind() == AttributeList::IgnoredAttribute) - continue; - Diag(Attr->getLoc(), - Attr->getKind() == AttributeList::UnknownAttribute - ? diag::warn_unknown_attribute_ignored - : diag::err_base_specifier_attribute) - << Attr->getName(); - } + for (const ParsedAttr &AL : Attributes) { + if (AL.isInvalid() || AL.getKind() == ParsedAttr::IgnoredAttribute) + continue; + Diag(AL.getLoc(), AL.getKind() == ParsedAttr::UnknownAttribute + ? diag::warn_unknown_attribute_ignored + : diag::err_base_specifier_attribute) + << AL.getName(); } TypeSourceInfo *TInfo = nullptr; @@ -2326,7 +2344,7 @@ Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange, /// locally, there's no need to abstract the small size parameter. typedef llvm::SmallPtrSet<QualType, 4> IndirectBaseSet; -/// \brief Recursively add the bases of Type. Don't add Type itself. +/// Recursively add the bases of Type. Don't add Type itself. static void NoteIndirectBases(ASTContext &Context, IndirectBaseSet &Set, const QualType &Type) @@ -2347,7 +2365,7 @@ NoteIndirectBases(ASTContext &Context, IndirectBaseSet &Set, } } -/// \brief Performs the actual work of attaching the given base class +/// Performs the actual work of attaching the given base class /// specifiers to a C++ class. bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, MutableArrayRef<CXXBaseSpecifier *> Bases) { @@ -2404,7 +2422,7 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, // The Microsoft extension __interface does not permit bases that // are not themselves public interfaces. Diag(KnownBase->getLocStart(), diag::err_invalid_base_in_interface) - << getRecordDiagFromTagKind(RD->getTagKind()) << RD->getName() + << getRecordDiagFromTagKind(RD->getTagKind()) << RD << RD->getSourceRange(); Invalid = true; } @@ -2417,9 +2435,16 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, // Attach the remaining base class specifiers to the derived class. Class->setBases(Bases.data(), NumGoodBases); + // Check that the only base classes that are duplicate are virtual. for (unsigned idx = 0; idx < NumGoodBases; ++idx) { // Check whether this direct base is inaccessible due to ambiguity. QualType BaseType = Bases[idx]->getType(); + + // Skip all dependent types in templates being used as base specifiers. + // Checks below assume that the base specifier is a CXXRecord. + if (BaseType->isDependentType()) + continue; + CanQualType CanonicalBase = Context.getCanonicalType(BaseType) .getUnqualifiedType(); @@ -2459,7 +2484,7 @@ void Sema::ActOnBaseSpecifiers(Decl *ClassDecl, AttachBaseSpecifiers(cast<CXXRecordDecl>(ClassDecl), Bases); } -/// \brief Determine whether the type \p Derived is a C++ class that is +/// Determine whether the type \p Derived is a C++ class that is /// derived from the type \p Base. bool Sema::IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base) { if (!getLangOpts().CPlusPlus) @@ -2486,7 +2511,7 @@ bool Sema::IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base) { return DerivedRD->isDerivedFrom(BaseRD); } -/// \brief Determine whether the type \p Derived is a C++ class that is +/// Determine whether the type \p Derived is a C++ class that is /// derived from the type \p Base. bool Sema::IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base, CXXBasePaths &Paths) { @@ -2638,7 +2663,7 @@ Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, } -/// @brief Builds a string representing ambiguous paths from a +/// Builds a string representing ambiguous paths from a /// specific derived class to different subobjects of the same base /// class. /// @@ -2674,10 +2699,9 @@ std::string Sema::getAmbiguousPathsDisplayString(CXXBasePaths &Paths) { //===----------------------------------------------------------------------===// /// ActOnAccessSpecifier - Parsed an access specifier followed by a colon. -bool Sema::ActOnAccessSpecifier(AccessSpecifier Access, - SourceLocation ASLoc, +bool Sema::ActOnAccessSpecifier(AccessSpecifier Access, SourceLocation ASLoc, SourceLocation ColonLoc, - AttributeList *Attrs) { + const ParsedAttributesView &Attrs) { assert(Access != AS_none && "Invalid kind for syntactic access specifier!"); AccessSpecDecl *ASDecl = AccessSpecDecl::Create(Context, Access, CurContext, ASLoc, ColonLoc); @@ -2764,7 +2788,7 @@ void Sema::DiagnoseAbsenceOfOverrideControl(NamedDecl *D) { SourceLocation Loc = MD->getLocation(); SourceLocation SpellingLoc = Loc; if (getSourceManager().isMacroArgExpansion(Loc)) - SpellingLoc = getSourceManager().getImmediateExpansionRange(Loc).first; + SpellingLoc = getSourceManager().getImmediateExpansionRange(Loc).getBegin(); SpellingLoc = getSourceManager().getSpellingLoc(SpellingLoc); if (SpellingLoc.isValid() && getSourceManager().isInSystemHeader(SpellingLoc)) return; @@ -2805,10 +2829,13 @@ static bool InitializationHasSideEffects(const FieldDecl &FD) { return false; } -static AttributeList *getMSPropertyAttr(AttributeList *list) { - for (AttributeList *it = list; it != nullptr; it = it->getNext()) - if (it->isDeclspecPropertyAttribute()) - return it; +static const ParsedAttr *getMSPropertyAttr(const ParsedAttributesView &list) { + ParsedAttributesView::const_iterator Itr = + llvm::find_if(list, [](const ParsedAttr &AL) { + return AL.isDeclspecPropertyAttribute(); + }); + if (Itr != list.end()) + return &*Itr; return nullptr; } @@ -2855,7 +2882,7 @@ void Sema::CheckShadowInheritedFields(const SourceLocation &Loc, if (AS_none != CXXRecordDecl::MergeAccess(P.Access, BaseField->getAccess())) { Diag(Loc, diag::warn_shadow_field) - << FieldName.getAsString() << RD->getName() << Base->getName(); + << FieldName << RD << Base; Diag(BaseField->getLocation(), diag::note_shadow_field); Bases.erase(It); } @@ -2887,8 +2914,8 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, assert(!DS.isFriendSpecified()); bool isFunc = D.isDeclarationOfFunction(); - AttributeList *MSPropertyAttr = - getMSPropertyAttr(D.getDeclSpec().getAttributes().getList()); + const ParsedAttr *MSPropertyAttr = + getMSPropertyAttr(D.getDeclSpec().getAttributes()); if (cast<CXXRecordDecl>(CurContext)->isInterface()) { // The Microsoft extension __interface only permits public member functions @@ -3044,7 +3071,9 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, // int X::member; // }; if (DeclContext *DC = computeDeclContext(SS, false)) - diagnoseQualifiedDeclaration(SS, DC, Name, D.getIdentifierLoc()); + diagnoseQualifiedDeclaration(SS, DC, Name, D.getIdentifierLoc(), + D.getName().getKind() == + UnqualifiedIdKind::IK_TemplateId); else Diag(D.getIdentifierLoc(), diag::err_member_qualification) << Name << SS.getRange(); @@ -3054,7 +3083,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, if (MSPropertyAttr) { Member = HandleMSProperty(S, cast<CXXRecordDecl>(CurContext), Loc, D, - BitWidth, InitStyle, AS, MSPropertyAttr); + BitWidth, InitStyle, AS, *MSPropertyAttr); if (!Member) return nullptr; isInstField = false; @@ -3096,14 +3125,38 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, Member->setInvalidDecl(); } + NamedDecl *NonTemplateMember = Member; + if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Member)) + NonTemplateMember = FunTmpl->getTemplatedDecl(); + else if (VarTemplateDecl *VarTmpl = dyn_cast<VarTemplateDecl>(Member)) + NonTemplateMember = VarTmpl->getTemplatedDecl(); + Member->setAccess(AS); // If we have declared a member function template or static data member // template, set the access of the templated declaration as well. - if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Member)) - FunTmpl->getTemplatedDecl()->setAccess(AS); - else if (VarTemplateDecl *VarTmpl = dyn_cast<VarTemplateDecl>(Member)) - VarTmpl->getTemplatedDecl()->setAccess(AS); + if (NonTemplateMember != Member) + NonTemplateMember->setAccess(AS); + + // C++ [temp.deduct.guide]p3: + // A deduction guide [...] for a member class template [shall be + // declared] with the same access [as the template]. + if (auto *DG = dyn_cast<CXXDeductionGuideDecl>(NonTemplateMember)) { + auto *TD = DG->getDeducedTemplate(); + if (AS != TD->getAccess()) { + Diag(DG->getLocStart(), diag::err_deduction_guide_wrong_access); + Diag(TD->getLocStart(), diag::note_deduction_guide_template_access) + << TD->getAccess(); + const AccessSpecDecl *LastAccessSpec = nullptr; + for (const auto *D : cast<CXXRecordDecl>(CurContext)->decls()) { + if (const auto *AccessSpec = dyn_cast<AccessSpecDecl>(D)) + LastAccessSpec = AccessSpec; + } + assert(LastAccessSpec && "differing access with no access specifier"); + Diag(LastAccessSpec->getLocStart(), diag::note_deduction_guide_access) + << AS; + } + } } if (VS.isOverrideSpecified()) @@ -3544,7 +3597,7 @@ namespace { } } // namespace -/// \brief Enter a new C++ default initializer scope. After calling this, the +/// Enter a new C++ default initializer scope. After calling this, the /// caller must call \ref ActOnFinishCXXInClassMemberInitializer, even if /// parsing or instantiating the initializer failed. void Sema::ActOnStartCXXInClassMemberInitializer() { @@ -3553,7 +3606,7 @@ void Sema::ActOnStartCXXInClassMemberInitializer() { PushFunctionScope(); } -/// \brief This is invoked after parsing an in-class initializer for a +/// This is invoked after parsing an in-class initializer for a /// non-static C++ class member, and after instantiating an in-class initializer /// in a class template. Such actions are deferred until the class is complete. void Sema::ActOnFinishCXXInClassMemberInitializer(Decl *D, @@ -3581,10 +3634,14 @@ void Sema::ActOnFinishCXXInClassMemberInitializer(Decl *D, ExprResult Init = InitExpr; if (!FD->getType()->isDependentType() && !InitExpr->isTypeDependent()) { - InitializedEntity Entity = InitializedEntity::InitializeMember(FD); - InitializationKind Kind = FD->getInClassInitStyle() == ICIS_ListInit - ? InitializationKind::CreateDirectList(InitExpr->getLocStart()) - : InitializationKind::CreateCopy(InitExpr->getLocStart(), InitLoc); + InitializedEntity Entity = + InitializedEntity::InitializeMemberFromDefaultMemberInitializer(FD); + InitializationKind Kind = + FD->getInClassInitStyle() == ICIS_ListInit + ? InitializationKind::CreateDirectList(InitExpr->getLocStart(), + InitExpr->getLocStart(), + InitExpr->getLocEnd()) + : InitializationKind::CreateCopy(InitExpr->getLocStart(), InitLoc); InitializationSequence Seq(*this, Entity, Kind, InitExpr); Init = Seq.Perform(*this, Entity, Kind, InitExpr); if (Init.isInvalid()) { @@ -3607,7 +3664,7 @@ void Sema::ActOnFinishCXXInClassMemberInitializer(Decl *D, FD->setInClassInitializer(InitExpr); } -/// \brief Find the direct and/or virtual base specifiers that +/// Find the direct and/or virtual base specifiers that /// correspond to the given base type, for use in base initialization /// within a constructor. static bool FindBaseInitializer(Sema &SemaRef, @@ -3651,7 +3708,7 @@ static bool FindBaseInitializer(Sema &SemaRef, return DirectBaseSpec || VirtualBaseSpec; } -/// \brief Handle a C++ member initializer using braced-init-list syntax. +/// Handle a C++ member initializer using braced-init-list syntax. MemInitResult Sema::ActOnMemInitializer(Decl *ConstructorD, Scope *S, @@ -3667,7 +3724,7 @@ Sema::ActOnMemInitializer(Decl *ConstructorD, EllipsisLoc); } -/// \brief Handle a C++ member initializer using parentheses syntax. +/// Handle a C++ member initializer using parentheses syntax. MemInitResult Sema::ActOnMemInitializer(Decl *ConstructorD, Scope *S, @@ -3710,7 +3767,7 @@ private: } -/// \brief Handle a C++ member initializer. +/// Handle a C++ member initializer. MemInitResult Sema::BuildMemInitializer(Decl *ConstructorD, Scope *S, @@ -3889,53 +3946,6 @@ Sema::BuildMemInitializer(Decl *ConstructorD, return BuildBaseInitializer(BaseType, TInfo, Init, ClassDecl, EllipsisLoc); } -/// Checks a member initializer expression for cases where reference (or -/// pointer) members are bound to by-value parameters (or their addresses). -static void CheckForDanglingReferenceOrPointer(Sema &S, ValueDecl *Member, - Expr *Init, - SourceLocation IdLoc) { - QualType MemberTy = Member->getType(); - - // We only handle pointers and references currently. - // FIXME: Would this be relevant for ObjC object pointers? Or block pointers? - if (!MemberTy->isReferenceType() && !MemberTy->isPointerType()) - return; - - const bool IsPointer = MemberTy->isPointerType(); - if (IsPointer) { - if (const UnaryOperator *Op - = dyn_cast<UnaryOperator>(Init->IgnoreParenImpCasts())) { - // The only case we're worried about with pointers requires taking the - // address. - if (Op->getOpcode() != UO_AddrOf) - return; - - Init = Op->getSubExpr(); - } else { - // We only handle address-of expression initializers for pointers. - return; - } - } - - if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Init->IgnoreParens())) { - // We only warn when referring to a non-reference parameter declaration. - const ParmVarDecl *Parameter = dyn_cast<ParmVarDecl>(DRE->getDecl()); - if (!Parameter || Parameter->getType()->isReferenceType()) - return; - - S.Diag(Init->getExprLoc(), - IsPointer ? diag::warn_init_ptr_member_to_parameter_addr - : diag::warn_bind_ref_member_to_parameter) - << Member << Parameter << Init->getSourceRange(); - } else { - // Other initializers are fine. - return; - } - - S.Diag(Member->getLocation(), diag::note_ref_or_ptr_member_declared_here) - << (unsigned)IsPointer; -} - MemInitResult Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init, SourceLocation IdLoc) { @@ -3979,9 +3989,10 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init, : InitializedEntity::InitializeMember(IndirectMember, nullptr); InitializationKind Kind = - InitList ? InitializationKind::CreateDirectList(IdLoc) - : InitializationKind::CreateDirect(IdLoc, InitRange.getBegin(), - InitRange.getEnd()); + InitList ? InitializationKind::CreateDirectList( + IdLoc, Init->getLocStart(), Init->getLocEnd()) + : InitializationKind::CreateDirect(IdLoc, InitRange.getBegin(), + InitRange.getEnd()); InitializationSequence InitSeq(*this, MemberEntity, Kind, Args); ExprResult MemberInit = InitSeq.Perform(*this, MemberEntity, Kind, Args, @@ -3989,8 +4000,6 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init, if (MemberInit.isInvalid()) return true; - CheckForDanglingReferenceOrPointer(*this, Member, MemberInit.get(), IdLoc); - // C++11 [class.base.init]p7: // The initialization of each base and member constitutes a // full-expression. @@ -4033,9 +4042,10 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init, InitializedEntity DelegationEntity = InitializedEntity::InitializeDelegation( QualType(ClassDecl->getTypeForDecl(), 0)); InitializationKind Kind = - InitList ? InitializationKind::CreateDirectList(NameLoc) - : InitializationKind::CreateDirect(NameLoc, InitRange.getBegin(), - InitRange.getEnd()); + InitList ? InitializationKind::CreateDirectList( + NameLoc, Init->getLocStart(), Init->getLocEnd()) + : InitializationKind::CreateDirect(NameLoc, InitRange.getBegin(), + InitRange.getEnd()); InitializationSequence InitSeq(*this, DelegationEntity, Kind, Args); ExprResult DelegationInit = InitSeq.Perform(*this, DelegationEntity, Kind, Args, nullptr); @@ -4167,9 +4177,9 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, InitializedEntity BaseEntity = InitializedEntity::InitializeBase(Context, BaseSpec, VirtualBaseSpec); InitializationKind Kind = - InitList ? InitializationKind::CreateDirectList(BaseLoc) - : InitializationKind::CreateDirect(BaseLoc, InitRange.getBegin(), - InitRange.getEnd()); + InitList ? InitializationKind::CreateDirectList(BaseLoc) + : InitializationKind::CreateDirect(BaseLoc, InitRange.getBegin(), + InitRange.getEnd()); InitializationSequence InitSeq(*this, BaseEntity, Kind, Args); ExprResult BaseInit = InitSeq.Perform(*this, BaseEntity, Kind, Args, nullptr); if (BaseInit.isInvalid()) @@ -4321,7 +4331,7 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, QualType ParamType = Param->getType().getNonReferenceType(); // Suppress copying zero-width bitfields. - if (Field->isBitField() && Field->getBitWidthValue(SemaRef.Context) == 0) + if (Field->isZeroLengthBitField(SemaRef.Context)) return false; Expr *MemberExprBase = @@ -4536,7 +4546,7 @@ struct BaseAndFieldInfo { return !FieldRD->hasInClassInitializer(); } - /// \brief Determine whether the given field is, or is within, a union member + /// Determine whether the given field is, or is within, a union member /// that is inactive (because there was an initializer given for a different /// member of the union, or because the union was not initialized at all). bool isWithinInactiveUnionMember(FieldDecl *Field, @@ -4554,7 +4564,7 @@ struct BaseAndFieldInfo { }; } -/// \brief Determine whether the given type is an incomplete or zero-lenfgth +/// Determine whether the given type is an incomplete or zero-lenfgth /// array type. static bool isIncompleteOrZeroLengthArrayType(ASTContext &Context, QualType T) { if (T->isIncompleteArrayType()) @@ -4601,6 +4611,10 @@ static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info, SemaRef.BuildCXXDefaultInitExpr(Info.Ctor->getLocation(), Field); if (DIE.isInvalid()) return true; + + auto Entity = InitializedEntity::InitializeMember(Field, nullptr, true); + SemaRef.checkInitializerLifetime(Entity, DIE.get()); + CXXCtorInitializer *Init; if (Indirect) Init = new (SemaRef.Context) @@ -5464,7 +5478,7 @@ static void CheckAbstractClassUsage(AbstractUsageInfo &Info, } } -static void ReferenceDllExportedMethods(Sema &S, CXXRecordDecl *Class) { +static void ReferenceDllExportedMembers(Sema &S, CXXRecordDecl *Class) { Attr *ClassAttr = getDLLAttr(Class); if (!ClassAttr) return; @@ -5479,6 +5493,14 @@ static void ReferenceDllExportedMethods(Sema &S, CXXRecordDecl *Class) { return; for (Decl *Member : Class->decls()) { + // Defined static variables that are members of an exported base + // class must be marked export too. + auto *VD = dyn_cast<VarDecl>(Member); + if (VD && Member->getAttr<DLLExportAttr>() && + VD->getStorageClass() == SC_Static && + TSK == TSK_ImplicitInstantiation) + S.MarkVariableReferenced(VD->getLocation(), VD); + auto *MD = dyn_cast<CXXMethodDecl>(Member); if (!MD) continue; @@ -5506,7 +5528,7 @@ static void ReferenceDllExportedMethods(Sema &S, CXXRecordDecl *Class) { S.MarkFunctionReferenced(Class->getLocation(), MD); if (Trap.hasErrorOccurred()) { S.Diag(ClassAttr->getLocation(), diag::note_due_to_dllexported_class) - << Class->getName() << !S.getLangOpts().CPlusPlus11; + << Class << !S.getLangOpts().CPlusPlus11; break; } @@ -5556,7 +5578,17 @@ static void checkForMultipleExportedDefaultConstructors(Sema &S, } } -/// \brief Check class-level dllimport/dllexport attribute. +void Sema::checkClassLevelCodeSegAttribute(CXXRecordDecl *Class) { + // Mark any compiler-generated routines with the implicit code_seg attribute. + for (auto *Method : Class->methods()) { + if (Method->isUserProvided()) + continue; + if (Attr *A = getImplicitCodeSegOrSectionAttrForFunction(Method, /*IsDefinition=*/true)) + Method->addAttr(A); + } +} + +/// Check class-level dllimport/dllexport attribute. void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) { Attr *ClassAttr = getDLLAttr(Class); @@ -5606,6 +5638,13 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) { // The class is either imported or exported. const bool ClassExported = ClassAttr->getKind() == attr::DLLExport; + // Check if this was a dllimport attribute propagated from a derived class to + // a base class template specialization. We don't apply these attributes to + // static data members. + const bool PropagatedImport = + !ClassExported && + cast<DLLImportAttr>(ClassAttr)->wasPropagatedToBaseTemplate(); + TemplateSpecializationKind TSK = Class->getTemplateSpecializationKind(); // Ignore explicit dllexport on explicit class template instantiation declarations. @@ -5657,6 +5696,11 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) { } } + // Don't apply dllimport attributes to static data members of class template + // instantiations when the attribute is propagated from a derived class. + if (VD && PropagatedImport) + continue; + if (!cast<NamedDecl>(Member)->isExternallyVisible()) continue; @@ -5665,6 +5709,21 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) { cast<InheritableAttr>(ClassAttr->clone(getASTContext())); NewAttr->setInherited(true); Member->addAttr(NewAttr); + + if (MD) { + // Propagate DLLAttr to friend re-declarations of MD that have already + // been constructed. + for (FunctionDecl *FD = MD->getMostRecentDecl(); FD; + FD = FD->getPreviousDecl()) { + if (FD->getFriendObjectKind() == Decl::FOK_None) + continue; + assert(!getDLLAttr(FD) && + "friend re-decl should not already have a DLLAttr"); + NewAttr = cast<InheritableAttr>(ClassAttr->clone(getASTContext())); + NewAttr->setInherited(true); + FD->addAttr(NewAttr); + } + } } } @@ -5672,7 +5731,7 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) { DelayedDllExportClasses.push_back(Class); } -/// \brief Perform propagation of DLL attributes from a derived class to a +/// Perform propagation of DLL attributes from a derived class to a /// templated base class for MS compatibility. void Sema::propagateDLLAttrToBaseClassTemplate( CXXRecordDecl *Class, Attr *ClassAttr, @@ -5694,6 +5753,11 @@ void Sema::propagateDLLAttrToBaseClassTemplate( NewAttr->setInherited(true); BaseTemplateSpec->addAttr(NewAttr); + // If this was an import, mark that we propagated it from a derived class to + // a base class template specialization. + if (auto *ImportAttr = dyn_cast<DLLImportAttr>(NewAttr)) + ImportAttr->setPropagatedToBaseTemplate(); + // If the template is already instantiated, checkDLLAttributeRedeclaration() // needs to be run again to work see the new attribute. Otherwise this will // get run whenever the template is instantiated. @@ -5756,10 +5820,74 @@ static void DefineImplicitSpecialMember(Sema &S, CXXMethodDecl *MD, /// Determine whether a type is permitted to be passed or returned in /// registers, per C++ [class.temporary]p3. -static bool computeCanPassInRegisters(Sema &S, CXXRecordDecl *D) { +static bool canPassInRegisters(Sema &S, CXXRecordDecl *D, + TargetInfo::CallingConvKind CCK) { if (D->isDependentType() || D->isInvalidDecl()) return false; + // Clang <= 4 used the pre-C++11 rule, which ignores move operations. + // The PS4 platform ABI follows the behavior of Clang 3.2. + if (CCK == TargetInfo::CCK_ClangABI4OrPS4) + return !D->hasNonTrivialDestructorForCall() && + !D->hasNonTrivialCopyConstructorForCall(); + + if (CCK == TargetInfo::CCK_MicrosoftWin64) { + bool CopyCtorIsTrivial = false, CopyCtorIsTrivialForCall = false; + bool DtorIsTrivialForCall = false; + + // If a class has at least one non-deleted, trivial copy constructor, it + // is passed according to the C ABI. Otherwise, it is passed indirectly. + // + // Note: This permits classes with non-trivial copy or move ctors to be + // passed in registers, so long as they *also* have a trivial copy ctor, + // which is non-conforming. + if (D->needsImplicitCopyConstructor()) { + if (!D->defaultedCopyConstructorIsDeleted()) { + if (D->hasTrivialCopyConstructor()) + CopyCtorIsTrivial = true; + if (D->hasTrivialCopyConstructorForCall()) + CopyCtorIsTrivialForCall = true; + } + } else { + for (const CXXConstructorDecl *CD : D->ctors()) { + if (CD->isCopyConstructor() && !CD->isDeleted()) { + if (CD->isTrivial()) + CopyCtorIsTrivial = true; + if (CD->isTrivialForCall()) + CopyCtorIsTrivialForCall = true; + } + } + } + + if (D->needsImplicitDestructor()) { + if (!D->defaultedDestructorIsDeleted() && + D->hasTrivialDestructorForCall()) + DtorIsTrivialForCall = true; + } else if (const auto *DD = D->getDestructor()) { + if (!DD->isDeleted() && DD->isTrivialForCall()) + DtorIsTrivialForCall = true; + } + + // If the copy ctor and dtor are both trivial-for-calls, pass direct. + if (CopyCtorIsTrivialForCall && DtorIsTrivialForCall) + return true; + + // If a class has a destructor, we'd really like to pass it indirectly + // because it allows us to elide copies. Unfortunately, MSVC makes that + // impossible for small types, which it will pass in a single register or + // stack slot. Most objects with dtors are large-ish, so handle that early. + // We can't call out all large objects as being indirect because there are + // multiple x64 calling conventions and the C++ ABI code shouldn't dictate + // how we pass large POD types. + + // Note: This permits small classes with nontrivial destructors to be + // passed in registers, which is non-conforming. + if (CopyCtorIsTrivial && + S.getASTContext().getTypeSize(D->getTypeForDecl()) <= 64) + return true; + return false; + } + // Per C++ [class.temporary]p3, the relevant condition is: // each copy constructor, move constructor, and destructor of X is // either trivial or deleted, and X has at least one non-deleted copy @@ -5768,20 +5896,20 @@ static bool computeCanPassInRegisters(Sema &S, CXXRecordDecl *D) { if (D->needsImplicitCopyConstructor() && !D->defaultedCopyConstructorIsDeleted()) { - if (!D->hasTrivialCopyConstructor()) + if (!D->hasTrivialCopyConstructorForCall()) return false; HasNonDeletedCopyOrMove = true; } if (S.getLangOpts().CPlusPlus11 && D->needsImplicitMoveConstructor() && !D->defaultedMoveConstructorIsDeleted()) { - if (!D->hasTrivialMoveConstructor()) + if (!D->hasTrivialMoveConstructorForCall()) return false; HasNonDeletedCopyOrMove = true; } if (D->needsImplicitDestructor() && !D->defaultedDestructorIsDeleted() && - !D->hasTrivialDestructor()) + !D->hasTrivialDestructorForCall()) return false; for (const CXXMethodDecl *MD : D->methods()) { @@ -5794,14 +5922,14 @@ static bool computeCanPassInRegisters(Sema &S, CXXRecordDecl *D) { else if (!isa<CXXDestructorDecl>(MD)) continue; - if (!MD->isTrivial()) + if (!MD->isTrivialForCall()) return false; } return HasNonDeletedCopyOrMove; } -/// \brief Perform semantic checks on a class definition that has been +/// Perform semantic checks on a class definition that has been /// completing, introducing implicitly-declared members, checking for /// abstract types, etc. void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { @@ -5851,10 +5979,11 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { DeclContext::lookup_result R = Record->lookup(Record->getDeclName()); for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; ++I) { - NamedDecl *D = *I; - if ((isa<FieldDecl>(D) && Record->hasUserDeclaredConstructor()) || + NamedDecl *D = (*I)->getUnderlyingDecl(); + if (((isa<FieldDecl>(D) || isa<UnresolvedUsingValueDecl>(D)) && + Record->hasUserDeclaredConstructor()) || isa<IndirectFieldDecl>(D)) { - Diag(D->getLocation(), diag::err_member_name_of_class) + Diag((*I)->getLocation(), diag::err_member_name_of_class) << D->getDeclName(); break; } @@ -5878,6 +6007,17 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { } } + // See if trivial_abi has to be dropped. + if (Record->hasAttr<TrivialABIAttr>()) + checkIllFormedTrivialABIStruct(*Record); + + // Set HasTrivialSpecialMemberForCall if the record has attribute + // "trivial_abi". + bool HasTrivialABI = Record->hasAttr<TrivialABIAttr>(); + + if (HasTrivialABI) + Record->setHasTrivialSpecialMemberForCall(); + bool HasMethodWithOverrideControl = false, HasOverridingMethodWithoutOverrideControl = false; if (!Record->isDependentType()) { @@ -5900,12 +6040,23 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { if (!M->isImplicit() && !M->isUserProvided()) { if (CSM != CXXInvalid) { M->setTrivial(SpecialMemberIsTrivial(M, CSM)); - // Inform the class that we've finished declaring this member. Record->finishedDefaultedOrDeletedMember(M); + M->setTrivialForCall( + HasTrivialABI || + SpecialMemberIsTrivial(M, CSM, TAH_ConsiderTrivialABI)); + Record->setTrivialForCallFlags(M); } } + // Set triviality for the purpose of calls if this is a user-provided + // copy/move constructor or destructor. + if ((CSM == CXXCopyConstructor || CSM == CXXMoveConstructor || + CSM == CXXDestructor) && M->isUserProvided()) { + M->setTrivialForCall(HasTrivialABI); + Record->setTrivialForCallFlags(M); + } + if (!M->isInvalidDecl() && M->isExplicitlyDefaulted() && M->hasAttr<DLLExportAttr>()) { if (getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015) && @@ -5945,8 +6096,35 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { } checkClassLevelDLLAttribute(Record); + checkClassLevelCodeSegAttribute(Record); + + bool ClangABICompat4 = + Context.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver4; + TargetInfo::CallingConvKind CCK = + Context.getTargetInfo().getCallingConvKind(ClangABICompat4); + bool CanPass = canPassInRegisters(*this, Record, CCK); + + // Do not change ArgPassingRestrictions if it has already been set to + // APK_CanNeverPassInRegs. + if (Record->getArgPassingRestrictions() != RecordDecl::APK_CanNeverPassInRegs) + Record->setArgPassingRestrictions(CanPass + ? RecordDecl::APK_CanPassInRegs + : RecordDecl::APK_CannotPassInRegs); - Record->setCanPassInRegisters(computeCanPassInRegisters(*this, Record)); + // If canPassInRegisters returns true despite the record having a non-trivial + // destructor, the record is destructed in the callee. This happens only when + // the record or one of its subobjects has a field annotated with trivial_abi + // or a field qualified with ObjC __strong/__weak. + if (Context.getTargetInfo().getCXXABI().areArgsDestroyedLeftToRightInCallee()) + Record->setParamDestroyedInCallee(true); + else if (Record->hasNonTrivialDestructor()) + Record->setParamDestroyedInCallee(CanPass); + + if (getLangOpts().ForceEmitVTables) { + // If we want to emit all the vtables, we need to mark it as used. This + // is especially required for cases like vtable assumption loads. + MarkVTableUsed(Record->getInnerLocStart(), Record); + } } /// Look up the special member function that would be called by a special @@ -7017,9 +7195,14 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, /// /// If \p Selected is not \c NULL, \c *Selected will be filled in with the /// member that was most likely to be intended to be trivial, if any. +/// +/// If \p ForCall is true, look at CXXRecord::HasTrivialSpecialMembersForCall to +/// determine whether the special member is trivial. static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD, Sema::CXXSpecialMember CSM, unsigned Quals, - bool ConstRHS, CXXMethodDecl **Selected) { + bool ConstRHS, + Sema::TrivialABIHandling TAH, + CXXMethodDecl **Selected) { if (Selected) *Selected = nullptr; @@ -7060,7 +7243,9 @@ static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD, // C++11 [class.dtor]p5: // A destructor is trivial if: // - all the direct [subobjects] have trivial destructors - if (RD->hasTrivialDestructor()) + if (RD->hasTrivialDestructor() || + (TAH == Sema::TAH_ConsiderTrivialABI && + RD->hasTrivialDestructorForCall())) return true; if (Selected) { @@ -7075,7 +7260,9 @@ static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD, // C++11 [class.copy]p12: // A copy constructor is trivial if: // - the constructor selected to copy each direct [subobject] is trivial - if (RD->hasTrivialCopyConstructor()) { + if (RD->hasTrivialCopyConstructor() || + (TAH == Sema::TAH_ConsiderTrivialABI && + RD->hasTrivialCopyConstructorForCall())) { if (Quals == Qualifiers::Const) // We must either select the trivial copy constructor or reach an // ambiguity; no need to actually perform overload resolution. @@ -7128,6 +7315,10 @@ static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD, // not supposed to! if (Selected) *Selected = SMOR.getMethod(); + + if (TAH == Sema::TAH_ConsiderTrivialABI && + (CSM == Sema::CXXCopyConstructor || CSM == Sema::CXXMoveConstructor)) + return SMOR.getMethod()->isTrivialForCall(); return SMOR.getMethod()->isTrivial(); } @@ -7166,14 +7357,14 @@ static bool checkTrivialSubobjectCall(Sema &S, SourceLocation SubobjLoc, QualType SubType, bool ConstRHS, Sema::CXXSpecialMember CSM, TrivialSubobjectKind Kind, - bool Diagnose) { + Sema::TrivialABIHandling TAH, bool Diagnose) { CXXRecordDecl *SubRD = SubType->getAsCXXRecordDecl(); if (!SubRD) return true; CXXMethodDecl *Selected; if (findTrivialSpecialMember(S, SubRD, CSM, SubType.getCVRQualifiers(), - ConstRHS, Diagnose ? &Selected : nullptr)) + ConstRHS, TAH, Diagnose ? &Selected : nullptr)) return true; if (Diagnose) { @@ -7203,7 +7394,8 @@ static bool checkTrivialSubobjectCall(Sema &S, SourceLocation SubobjLoc, << Kind << SubType.getUnqualifiedType() << CSM; // Explain why the defaulted or deleted special member isn't trivial. - S.SpecialMemberIsTrivial(Selected, CSM, Diagnose); + S.SpecialMemberIsTrivial(Selected, CSM, Sema::TAH_IgnoreTrivialABI, + Diagnose); } } @@ -7214,7 +7406,9 @@ static bool checkTrivialSubobjectCall(Sema &S, SourceLocation SubobjLoc, /// trivial. static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD, Sema::CXXSpecialMember CSM, - bool ConstArg, bool Diagnose) { + bool ConstArg, + Sema::TrivialABIHandling TAH, + bool Diagnose) { for (const auto *FI : RD->fields()) { if (FI->isInvalidDecl() || FI->isUnnamedBitfield()) continue; @@ -7224,7 +7418,7 @@ static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD, // Pretend anonymous struct or union members are members of this class. if (FI->isAnonymousStructOrUnion()) { if (!checkTrivialClassMembers(S, FieldType->getAsCXXRecordDecl(), - CSM, ConstArg, Diagnose)) + CSM, ConstArg, TAH, Diagnose)) return false; continue; } @@ -7252,7 +7446,7 @@ static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD, bool ConstRHS = ConstArg && !FI->isMutable(); if (!checkTrivialSubobjectCall(S, FI->getLocation(), FieldType, ConstRHS, - CSM, TSK_Field, Diagnose)) + CSM, TSK_Field, TAH, Diagnose)) return false; } @@ -7266,14 +7460,15 @@ void Sema::DiagnoseNontrivial(const CXXRecordDecl *RD, CXXSpecialMember CSM) { bool ConstArg = (CSM == CXXCopyConstructor || CSM == CXXCopyAssignment); checkTrivialSubobjectCall(*this, RD->getLocation(), Ty, ConstArg, CSM, - TSK_CompleteObject, /*Diagnose*/true); + TSK_CompleteObject, TAH_IgnoreTrivialABI, + /*Diagnose*/true); } /// Determine whether a defaulted or deleted special member function is trivial, /// as specified in C++11 [class.ctor]p5, C++11 [class.copy]p12, /// C++11 [class.copy]p25, and C++11 [class.dtor]p5. bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM, - bool Diagnose) { + TrivialABIHandling TAH, bool Diagnose) { assert(!MD->isUserProvided() && CSM != CXXInvalid && "not special enough"); CXXRecordDecl *RD = MD->getParent(); @@ -7350,7 +7545,7 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM, // destructors] for (const auto &BI : RD->bases()) if (!checkTrivialSubobjectCall(*this, BI.getLocStart(), BI.getType(), - ConstArg, CSM, TSK_BaseClass, Diagnose)) + ConstArg, CSM, TSK_BaseClass, TAH, Diagnose)) return false; // C++11 [class.ctor]p5, C++11 [class.dtor]p5: @@ -7365,7 +7560,7 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM, // -- for all of the non-static data members of its class that are of class // type (or array thereof), each such class has a trivial [default // constructor or destructor] - if (!checkTrivialClassMembers(*this, RD, CSM, ConstArg, Diagnose)) + if (!checkTrivialClassMembers(*this, RD, CSM, ConstArg, TAH, Diagnose)) return false; // C++11 [class.dtor]p5: @@ -7477,7 +7672,7 @@ public: }; } // end anonymous namespace -/// \brief Add the most overriden methods from MD to Methods +/// Add the most overriden methods from MD to Methods static void AddMostOverridenMethods(const CXXMethodDecl *MD, llvm::SmallPtrSetImpl<const CXXMethodDecl *>& Methods) { if (MD->size_overridden_methods() == 0) @@ -7487,7 +7682,7 @@ static void AddMostOverridenMethods(const CXXMethodDecl *MD, AddMostOverridenMethods(O, Methods); } -/// \brief Check if a method overloads virtual methods in a base class without +/// Check if a method overloads virtual methods in a base class without /// overriding any. void Sema::FindHiddenVirtualMethods(CXXMethodDecl *MD, SmallVectorImpl<CXXMethodDecl*> &OverloadedMethods) { @@ -7528,7 +7723,7 @@ void Sema::NoteHiddenVirtualMethods(CXXMethodDecl *MD, } } -/// \brief Diagnose methods which overload virtual methods in a base class +/// Diagnose methods which overload virtual methods in a base class /// without overriding any. void Sema::DiagnoseHiddenVirtualMethods(CXXMethodDecl *MD) { if (MD->isInvalidDecl()) @@ -7547,22 +7742,64 @@ void Sema::DiagnoseHiddenVirtualMethods(CXXMethodDecl *MD) { } } -void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, - Decl *TagDecl, - SourceLocation LBrac, - SourceLocation RBrac, - AttributeList *AttrList) { +void Sema::checkIllFormedTrivialABIStruct(CXXRecordDecl &RD) { + auto PrintDiagAndRemoveAttr = [&]() { + // No diagnostics if this is a template instantiation. + if (!isTemplateInstantiation(RD.getTemplateSpecializationKind())) + Diag(RD.getAttr<TrivialABIAttr>()->getLocation(), + diag::ext_cannot_use_trivial_abi) << &RD; + RD.dropAttr<TrivialABIAttr>(); + }; + + // Ill-formed if the struct has virtual functions. + if (RD.isPolymorphic()) { + PrintDiagAndRemoveAttr(); + return; + } + + for (const auto &B : RD.bases()) { + // Ill-formed if the base class is non-trivial for the purpose of calls or a + // virtual base. + if ((!B.getType()->isDependentType() && + !B.getType()->getAsCXXRecordDecl()->canPassInRegisters()) || + B.isVirtual()) { + PrintDiagAndRemoveAttr(); + return; + } + } + + for (const auto *FD : RD.fields()) { + // Ill-formed if the field is an ObjectiveC pointer or of a type that is + // non-trivial for the purpose of calls. + QualType FT = FD->getType(); + if (FT.getObjCLifetime() == Qualifiers::OCL_Weak) { + PrintDiagAndRemoveAttr(); + return; + } + + if (const auto *RT = FT->getBaseElementTypeUnsafe()->getAs<RecordType>()) + if (!RT->isDependentType() && + !cast<CXXRecordDecl>(RT->getDecl())->canPassInRegisters()) { + PrintDiagAndRemoveAttr(); + return; + } + } +} + +void Sema::ActOnFinishCXXMemberSpecification( + Scope *S, SourceLocation RLoc, Decl *TagDecl, SourceLocation LBrac, + SourceLocation RBrac, const ParsedAttributesView &AttrList) { if (!TagDecl) return; AdjustDeclIfTemplate(TagDecl); - for (const AttributeList* l = AttrList; l; l = l->getNext()) { - if (l->getKind() != AttributeList::AT_Visibility) + for (const ParsedAttr &AL : AttrList) { + if (AL.getKind() != ParsedAttr::AT_Visibility) continue; - l->setInvalid(); - Diag(l->getLoc(), diag::warn_attribute_after_definition_ignored) << - l->getName(); + AL.setInvalid(); + Diag(AL.getLoc(), diag::warn_attribute_after_definition_ignored) + << AL.getName(); } ActOnFields(S, RLoc, TagDecl, llvm::makeArrayRef( @@ -7570,7 +7807,7 @@ void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, reinterpret_cast<Decl**>(FieldCollector->getCurFields()), FieldCollector->getCurNumFields()), LBrac, RBrac, AttrList); - CheckCompletedCXXClass(dyn_cast_or_null<CXXRecordDecl>(TagDecl)); + CheckCompletedCXXClass(cast<CXXRecordDecl>(TagDecl)); } /// AddImplicitlyDeclaredMembersToClass - Adds any implicitly-declared @@ -8108,7 +8345,8 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R, QualType ConvType = GetTypeFromParser(D.getName().ConversionFunctionId, &ConvTSI); - if (D.getDeclSpec().hasTypeSpecifier() && !D.isInvalidType()) { + const DeclSpec &DS = D.getDeclSpec(); + if (DS.hasTypeSpecifier() && !D.isInvalidType()) { // Conversion functions don't have return types, but the parser will // happily parse something like: // @@ -8118,9 +8356,18 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R, // // The return type will be changed later anyway. Diag(D.getIdentifierLoc(), diag::err_conv_function_return_type) - << SourceRange(D.getDeclSpec().getTypeSpecTypeLoc()) + << SourceRange(DS.getTypeSpecTypeLoc()) << SourceRange(D.getIdentifierLoc()); D.setInvalidType(); + } else if (DS.getTypeQualifiers() && !D.isInvalidType()) { + // It's also plausible that the user writes type qualifiers in the wrong + // place, such as: + // struct S { const operator int(); }; + // FIXME: we could provide a fixit to move the qualifiers onto the + // conversion type. + Diag(D.getIdentifierLoc(), diag::err_conv_function_with_complex_decl) + << SourceRange(D.getIdentifierLoc()) << 0; + D.setInvalidType(); } const FunctionProtoType *Proto = R->getAs<FunctionProtoType>(); @@ -8233,12 +8480,12 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R, R = Context.getFunctionType(ConvType, None, Proto->getExtProtoInfo()); // C++0x explicit conversion operators. - if (D.getDeclSpec().isExplicitSpecified()) - Diag(D.getDeclSpec().getExplicitSpecLoc(), - getLangOpts().CPlusPlus11 ? - diag::warn_cxx98_compat_explicit_conversion_functions : - diag::ext_explicit_conversion_functions) - << SourceRange(D.getDeclSpec().getExplicitSpecLoc()); + if (DS.isExplicitSpecified()) + Diag(DS.getExplicitSpecLoc(), + getLangOpts().CPlusPlus11 + ? diag::warn_cxx98_compat_explicit_conversion_functions + : diag::ext_explicit_conversion_functions) + << SourceRange(DS.getExplicitSpecLoc()); } /// ActOnConversionDeclarator - Called by ActOnDeclarator to complete @@ -8437,7 +8684,7 @@ void Sema::CheckDeductionGuideDeclarator(Declarator &D, QualType &R, // Namespace Handling //===----------------------------------------------------------------------===// -/// \brief Diagnose a mismatch in 'inline' qualifiers when a namespace is +/// Diagnose a mismatch in 'inline' qualifiers when a namespace is /// reopened. static void DiagnoseNamespaceInlineMismatch(Sema &S, SourceLocation KeywordLoc, SourceLocation Loc, @@ -8479,14 +8726,10 @@ static void DiagnoseNamespaceInlineMismatch(Sema &S, SourceLocation KeywordLoc, /// ActOnStartNamespaceDef - This is called at the start of a namespace /// definition. -Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, - SourceLocation InlineLoc, - SourceLocation NamespaceLoc, - SourceLocation IdentLoc, - IdentifierInfo *II, - SourceLocation LBrace, - AttributeList *AttrList, - UsingDirectiveDecl *&UD) { +Decl *Sema::ActOnStartNamespaceDef( + Scope *NamespcScope, SourceLocation InlineLoc, SourceLocation NamespaceLoc, + SourceLocation IdentLoc, IdentifierInfo *II, SourceLocation LBrace, + const ParsedAttributesView &AttrList, UsingDirectiveDecl *&UD) { SourceLocation StartLoc = InlineLoc.isValid() ? InlineLoc : NamespaceLoc; // For anonymous namespace, take the location of the left brace. SourceLocation Loc = II ? IdentLoc : LBrace; @@ -8673,7 +8916,137 @@ NamespaceDecl *Sema::lookupStdExperimentalNamespace() { return StdExperimentalNamespaceCache; } -/// \brief Retrieve the special "std" namespace, which may require us to +namespace { + +enum UnsupportedSTLSelect { + USS_InvalidMember, + USS_MissingMember, + USS_NonTrivial, + USS_Other +}; + +struct InvalidSTLDiagnoser { + Sema &S; + SourceLocation Loc; + QualType TyForDiags; + + QualType operator()(UnsupportedSTLSelect Sel = USS_Other, StringRef Name = "", + const VarDecl *VD = nullptr) { + { + auto D = S.Diag(Loc, diag::err_std_compare_type_not_supported) + << TyForDiags << ((int)Sel); + if (Sel == USS_InvalidMember || Sel == USS_MissingMember) { + assert(!Name.empty()); + D << Name; + } + } + if (Sel == USS_InvalidMember) { + S.Diag(VD->getLocation(), diag::note_var_declared_here) + << VD << VD->getSourceRange(); + } + return QualType(); + } +}; +} // namespace + +QualType Sema::CheckComparisonCategoryType(ComparisonCategoryType Kind, + SourceLocation Loc) { + assert(getLangOpts().CPlusPlus && + "Looking for comparison category type outside of C++."); + + // Check if we've already successfully checked the comparison category type + // before. If so, skip checking it again. + ComparisonCategoryInfo *Info = Context.CompCategories.lookupInfo(Kind); + if (Info && FullyCheckedComparisonCategories[static_cast<unsigned>(Kind)]) + return Info->getType(); + + // If lookup failed + if (!Info) { + std::string NameForDiags = "std::"; + NameForDiags += ComparisonCategories::getCategoryString(Kind); + Diag(Loc, diag::err_implied_comparison_category_type_not_found) + << NameForDiags; + return QualType(); + } + + assert(Info->Kind == Kind); + assert(Info->Record); + + // Update the Record decl in case we encountered a forward declaration on our + // first pass. FIXME: This is a bit of a hack. + if (Info->Record->hasDefinition()) + Info->Record = Info->Record->getDefinition(); + + // Use an elaborated type for diagnostics which has a name containing the + // prepended 'std' namespace but not any inline namespace names. + QualType TyForDiags = [&]() { + auto *NNS = + NestedNameSpecifier::Create(Context, nullptr, getStdNamespace()); + return Context.getElaboratedType(ETK_None, NNS, Info->getType()); + }(); + + if (RequireCompleteType(Loc, TyForDiags, diag::err_incomplete_type)) + return QualType(); + + InvalidSTLDiagnoser UnsupportedSTLError{*this, Loc, TyForDiags}; + + if (!Info->Record->isTriviallyCopyable()) + return UnsupportedSTLError(USS_NonTrivial); + + for (const CXXBaseSpecifier &BaseSpec : Info->Record->bases()) { + CXXRecordDecl *Base = BaseSpec.getType()->getAsCXXRecordDecl(); + // Tolerate empty base classes. + if (Base->isEmpty()) + continue; + // Reject STL implementations which have at least one non-empty base. + return UnsupportedSTLError(); + } + + // Check that the STL has implemented the types using a single integer field. + // This expectation allows better codegen for builtin operators. We require: + // (1) The class has exactly one field. + // (2) The field is an integral or enumeration type. + auto FIt = Info->Record->field_begin(), FEnd = Info->Record->field_end(); + if (std::distance(FIt, FEnd) != 1 || + !FIt->getType()->isIntegralOrEnumerationType()) { + return UnsupportedSTLError(); + } + + // Build each of the require values and store them in Info. + for (ComparisonCategoryResult CCR : + ComparisonCategories::getPossibleResultsForType(Kind)) { + StringRef MemName = ComparisonCategories::getResultString(CCR); + ComparisonCategoryInfo::ValueInfo *ValInfo = Info->lookupValueInfo(CCR); + + if (!ValInfo) + return UnsupportedSTLError(USS_MissingMember, MemName); + + VarDecl *VD = ValInfo->VD; + assert(VD && "should not be null!"); + + // Attempt to diagnose reasons why the STL definition of this type + // might be foobar, including it failing to be a constant expression. + // TODO Handle more ways the lookup or result can be invalid. + if (!VD->isStaticDataMember() || !VD->isConstexpr() || !VD->hasInit() || + !VD->checkInitIsICE()) + return UnsupportedSTLError(USS_InvalidMember, MemName, VD); + + // Attempt to evaluate the var decl as a constant expression and extract + // the value of its first field as a ICE. If this fails, the STL + // implementation is not supported. + if (!ValInfo->hasValidIntValue()) + return UnsupportedSTLError(); + + MarkVariableReferenced(Loc, VD); + } + + // We've successfully built the required types and expressions. Update + // the cache and return the newly cached value. + FullyCheckedComparisonCategories[static_cast<unsigned>(Kind)] = true; + return Info->getType(); +} + +/// Retrieve the special "std" namespace, which may require us to /// implicitly define the namespace. NamespaceDecl *Sema::getOrCreateStdNamespace() { if (!StdNamespace) { @@ -8816,7 +9189,7 @@ bool Sema::isInitListConstructor(const FunctionDecl *Ctor) { return isStdInitializerList(ArgType, nullptr); } -/// \brief Determine whether a using statement is in a context where it will be +/// Determine whether a using statement is in a context where it will be /// apply in all contexts. static bool IsUsingDirectiveInToplevelContext(DeclContext *CurContext) { switch (CurContext->getDeclKind()) { @@ -8871,13 +9244,11 @@ static bool TryNamespaceTypoCorrection(Sema &S, LookupResult &R, Scope *Sc, return false; } -Decl *Sema::ActOnUsingDirective(Scope *S, - SourceLocation UsingLoc, - SourceLocation NamespcLoc, - CXXScopeSpec &SS, - SourceLocation IdentLoc, - IdentifierInfo *NamespcName, - AttributeList *AttrList) { +Decl *Sema::ActOnUsingDirective(Scope *S, SourceLocation UsingLoc, + SourceLocation NamespcLoc, CXXScopeSpec &SS, + SourceLocation IdentLoc, + IdentifierInfo *NamespcName, + const ParsedAttributesView &AttrList) { assert(!SS.isInvalid() && "Invalid CXXScopeSpec."); assert(NamespcName && "Invalid NamespcName."); assert(IdentLoc.isValid() && "Invalid NamespceName location."); @@ -8932,7 +9303,7 @@ Decl *Sema::ActOnUsingDirective(Scope *S, // Find enclosing context containing both using-directive and // nominated namespace. - DeclContext *CommonAncestor = cast<DeclContext>(NS); + DeclContext *CommonAncestor = NS; while (CommonAncestor && !CommonAncestor->Encloses(CurContext)) CommonAncestor = CommonAncestor->getParent(); @@ -8969,15 +9340,12 @@ void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) { S->PushUsingDirective(UDir); } - -Decl *Sema::ActOnUsingDeclaration(Scope *S, - AccessSpecifier AS, +Decl *Sema::ActOnUsingDeclaration(Scope *S, AccessSpecifier AS, SourceLocation UsingLoc, - SourceLocation TypenameLoc, - CXXScopeSpec &SS, + SourceLocation TypenameLoc, CXXScopeSpec &SS, UnqualifiedId &Name, SourceLocation EllipsisLoc, - AttributeList *AttrList) { + const ParsedAttributesView &AttrList) { assert(S->getFlags() & Scope::DeclScope && "Invalid Scope."); if (SS.isEmpty()) { @@ -8986,15 +9354,15 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S, } switch (Name.getKind()) { - case UnqualifiedId::IK_ImplicitSelfParam: - case UnqualifiedId::IK_Identifier: - case UnqualifiedId::IK_OperatorFunctionId: - case UnqualifiedId::IK_LiteralOperatorId: - case UnqualifiedId::IK_ConversionFunctionId: + case UnqualifiedIdKind::IK_ImplicitSelfParam: + case UnqualifiedIdKind::IK_Identifier: + case UnqualifiedIdKind::IK_OperatorFunctionId: + case UnqualifiedIdKind::IK_LiteralOperatorId: + case UnqualifiedIdKind::IK_ConversionFunctionId: break; - case UnqualifiedId::IK_ConstructorName: - case UnqualifiedId::IK_ConstructorTemplateId: + case UnqualifiedIdKind::IK_ConstructorName: + case UnqualifiedIdKind::IK_ConstructorTemplateId: // C++11 inheriting constructors. Diag(Name.getLocStart(), getLangOpts().CPlusPlus11 ? @@ -9006,17 +9374,17 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S, return nullptr; - case UnqualifiedId::IK_DestructorName: + case UnqualifiedIdKind::IK_DestructorName: Diag(Name.getLocStart(), diag::err_using_decl_destructor) << SS.getRange(); return nullptr; - case UnqualifiedId::IK_TemplateId: + case UnqualifiedIdKind::IK_TemplateId: Diag(Name.getLocStart(), diag::err_using_decl_template_id) << SourceRange(Name.TemplateId->LAngleLoc, Name.TemplateId->RAngleLoc); return nullptr; - case UnqualifiedId::IK_DeductionGuideName: + case UnqualifiedIdKind::IK_DeductionGuideName: llvm_unreachable("cannot parse qualified deduction guide name"); } @@ -9056,7 +9424,7 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S, return UD; } -/// \brief Determine whether a using declaration considers the given +/// Determine whether a using declaration considers the given /// declarations as "equivalent", e.g., if they are redeclarations of /// the same entity or are both typedefs of the same type. static bool @@ -9149,6 +9517,19 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, if (isa<UsingDecl>(D) || isa<UsingPackDecl>(D)) continue; + if (auto *RD = dyn_cast<CXXRecordDecl>(D)) { + // C++ [class.mem]p19: + // If T is the name of a class, then [every named member other than + // a non-static data member] shall have a name different from T + if (RD->isInjectedClassName() && !isa<FieldDecl>(Target) && + !isa<IndirectFieldDecl>(Target) && + !isa<UnresolvedUsingValueDecl>(Target) && + DiagnoseClassNameShadow( + CurContext, + DeclarationNameInfo(Using->getDeclName(), Using->getLocation()))) + return true; + } + if (IsEquivalentForUsingDecl(Context, D, Target)) { if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(*I)) PrevShadow = Shadow; @@ -9421,15 +9802,11 @@ private: /// \param IsInstantiation - Whether this call arises from an /// instantiation of an unresolved using declaration. We treat /// the lookup differently for these declarations. -NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, - SourceLocation UsingLoc, - bool HasTypenameKeyword, - SourceLocation TypenameLoc, - CXXScopeSpec &SS, - DeclarationNameInfo NameInfo, - SourceLocation EllipsisLoc, - AttributeList *AttrList, - bool IsInstantiation) { +NamedDecl *Sema::BuildUsingDeclaration( + Scope *S, AccessSpecifier AS, SourceLocation UsingLoc, + bool HasTypenameKeyword, SourceLocation TypenameLoc, CXXScopeSpec &SS, + DeclarationNameInfo NameInfo, SourceLocation EllipsisLoc, + const ParsedAttributesView &AttrList, bool IsInstantiation) { assert(!SS.isInvalid() && "Invalid CXXScopeSpec."); SourceLocation IdentLoc = NameInfo.getLoc(); assert(IdentLoc.isValid() && "Invalid TargetName location."); @@ -9995,14 +10372,11 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc, return true; } -Decl *Sema::ActOnAliasDeclaration(Scope *S, - AccessSpecifier AS, +Decl *Sema::ActOnAliasDeclaration(Scope *S, AccessSpecifier AS, MultiTemplateParamsArg TemplateParamLists, - SourceLocation UsingLoc, - UnqualifiedId &Name, - AttributeList *AttrList, - TypeResult Type, - Decl *DeclFromDeclSpec) { + SourceLocation UsingLoc, UnqualifiedId &Name, + const ParsedAttributesView &AttrList, + TypeResult Type, Decl *DeclFromDeclSpec) { // Skip up to the relevant declaration scope. while (S->isTemplateParamScope()) S = S->getParent(); @@ -10040,7 +10414,7 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S, Previous.clear(); } - assert(Name.Kind == UnqualifiedId::IK_Identifier && + assert(Name.Kind == UnqualifiedIdKind::IK_Identifier && "name in alias declaration must be an identifier"); TypeAliasDecl *NewTD = TypeAliasDecl::Create(Context, CurContext, UsingLoc, Name.StartLocation, @@ -10378,7 +10752,7 @@ struct DeclaringSpecialMember { } } - /// \brief Are we already trying to declare this special member? + /// Are we already trying to declare this special member? bool isAlreadyBeingDeclared() const { return WasAlreadyBeingDeclared; } @@ -10720,6 +11094,8 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) { // We don't need to use SpecialMemberIsTrivial here; triviality for // destructors is easy to compute. Destructor->setTrivial(ClassDecl->hasTrivialDestructor()); + Destructor->setTrivialForCall(ClassDecl->hasAttr<TrivialABIAttr>() || + ClassDecl->hasTrivialDestructorForCall()); // Note that we have declared this destructor. ++ASTContext::NumImplicitDestructorsDeclared; @@ -10784,7 +11160,7 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation, } } -/// \brief Perform any semantic analysis which needs to be delayed until all +/// Perform any semantic analysis which needs to be delayed until all /// pending class member declarations have been parsed. void Sema::ActOnFinishCXXMemberDecls() { // If the context is an invalid C++ class, just suppress these checks. @@ -10804,12 +11180,12 @@ void Sema::ActOnFinishCXXNonNestedClass(Decl *D) { void Sema::referenceDLLExportedClassMethods() { if (!DelayedDllExportClasses.empty()) { - // Calling ReferenceDllExportedMethods might cause the current function to + // Calling ReferenceDllExportedMembers might cause the current function to // be called again, so use a local copy of DelayedDllExportClasses. SmallVector<CXXRecordDecl *, 4> WorkList; std::swap(DelayedDllExportClasses, WorkList); for (CXXRecordDecl *Class : WorkList) - ReferenceDllExportedMethods(*this, Class); + ReferenceDllExportedMembers(*this, Class); } } @@ -10843,7 +11219,7 @@ void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl, } namespace { -/// \brief An abstract base class for all helper classes used in building the +/// An abstract base class for all helper classes used in building the // copy/move operators. These classes serve as factory functions and help us // avoid using the same Expr* in the AST twice. class ExprBuilder { @@ -10990,11 +11366,11 @@ buildMemcpyForAssignmentOp(Sema &S, SourceLocation Loc, QualType T, Expr *From = FromB.build(S, Loc); From = new (S.Context) UnaryOperator(From, UO_AddrOf, S.Context.getPointerType(From->getType()), - VK_RValue, OK_Ordinary, Loc); + VK_RValue, OK_Ordinary, Loc, false); Expr *To = ToB.build(S, Loc); To = new (S.Context) UnaryOperator(To, UO_AddrOf, S.Context.getPointerType(To->getType()), - VK_RValue, OK_Ordinary, Loc); + VK_RValue, OK_Ordinary, Loc, false); const Type *E = T->getBaseElementTypeUnsafe(); bool NeedsCollectableMemCpy = @@ -11028,7 +11404,7 @@ buildMemcpyForAssignmentOp(Sema &S, SourceLocation Loc, QualType T, return Call.getAs<Stmt>(); } -/// \brief Builds a statement that copies/moves the given entity from \p From to +/// Builds a statement that copies/moves the given entity from \p From to /// \c To. /// /// This routine is used to copy/move the members of a class with an @@ -11233,10 +11609,12 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T, BO_NE, S.Context.BoolTy, VK_RValue, OK_Ordinary, Loc, FPOptions()); - // Create the pre-increment of the iteration variable. - Expr *Increment - = new (S.Context) UnaryOperator(IterationVarRef.build(S, Loc), UO_PreInc, - SizeType, VK_LValue, OK_Ordinary, Loc); + // Create the pre-increment of the iteration variable. We can determine + // whether the increment will overflow based on the value of the array + // bound. + Expr *Increment = new (S.Context) + UnaryOperator(IterationVarRef.build(S, Loc), UO_PreInc, SizeType, + VK_LValue, OK_Ordinary, Loc, Upper.isMaxValue()); // Construct the loop that copies all elements of this array. return S.ActOnForStmt( @@ -11525,7 +11903,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, } // Suppress assigning zero-width bitfields. - if (Field->isBitField() && Field->getBitWidthValue(Context) == 0) + if (Field->isZeroLengthBitField(Context)) continue; QualType FieldType = Field->getType().getNonReferenceType(); @@ -11892,7 +12270,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, } // Suppress assigning zero-width bitfields. - if (Field->isBitField() && Field->getBitWidthValue(Context) == 0) + if (Field->isZeroLengthBitField(Context)) continue; QualType FieldType = Field->getType().getNonReferenceType(); @@ -12021,9 +12399,16 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( CopyConstructor->setParams(FromParam); CopyConstructor->setTrivial( - ClassDecl->needsOverloadResolutionForCopyConstructor() - ? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor) - : ClassDecl->hasTrivialCopyConstructor()); + ClassDecl->needsOverloadResolutionForCopyConstructor() + ? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor) + : ClassDecl->hasTrivialCopyConstructor()); + + CopyConstructor->setTrivialForCall( + ClassDecl->hasAttr<TrivialABIAttr>() || + (ClassDecl->needsOverloadResolutionForCopyConstructor() + ? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor, + TAH_ConsiderTrivialABI) + : ClassDecl->hasTrivialCopyConstructorForCall())); // Note that we have declared this constructor. ++ASTContext::NumImplicitCopyConstructorsDeclared; @@ -12144,9 +12529,16 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor( MoveConstructor->setParams(FromParam); MoveConstructor->setTrivial( - ClassDecl->needsOverloadResolutionForMoveConstructor() - ? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor) - : ClassDecl->hasTrivialMoveConstructor()); + ClassDecl->needsOverloadResolutionForMoveConstructor() + ? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor) + : ClassDecl->hasTrivialMoveConstructor()); + + MoveConstructor->setTrivialForCall( + ClassDecl->hasAttr<TrivialABIAttr>() || + (ClassDecl->needsOverloadResolutionForMoveConstructor() + ? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor, + TAH_ConsiderTrivialABI) + : ClassDecl->hasTrivialMoveConstructorForCall())); // Note that we have declared this constructor. ++ASTContext::NumImplicitMoveConstructorsDeclared; @@ -12215,30 +12607,27 @@ void Sema::DefineImplicitLambdaToFunctionPointerConversion( SourceLocation CurrentLocation, CXXConversionDecl *Conv) { SynthesizedFunctionScope Scope(*this, Conv); + assert(!Conv->getReturnType()->isUndeducedType()); CXXRecordDecl *Lambda = Conv->getParent(); - CXXMethodDecl *CallOp = Lambda->getLambdaCallOperator(); - // If we are defining a specialization of a conversion to function-ptr - // cache the deduced template arguments for this specialization - // so that we can use them to retrieve the corresponding call-operator - // and static-invoker. - const TemplateArgumentList *DeducedTemplateArgs = nullptr; - - // Retrieve the corresponding call-operator specialization. - if (Lambda->isGenericLambda()) { - assert(Conv->isFunctionTemplateSpecialization()); - FunctionTemplateDecl *CallOpTemplate = - CallOp->getDescribedFunctionTemplate(); - DeducedTemplateArgs = Conv->getTemplateSpecializationArgs(); - void *InsertPos = nullptr; - FunctionDecl *CallOpSpec = CallOpTemplate->findSpecialization( - DeducedTemplateArgs->asArray(), - InsertPos); - assert(CallOpSpec && - "Conversion operator must have a corresponding call operator"); - CallOp = cast<CXXMethodDecl>(CallOpSpec); + FunctionDecl *CallOp = Lambda->getLambdaCallOperator(); + FunctionDecl *Invoker = Lambda->getLambdaStaticInvoker(); + + if (auto *TemplateArgs = Conv->getTemplateSpecializationArgs()) { + CallOp = InstantiateFunctionDeclaration( + CallOp->getDescribedFunctionTemplate(), TemplateArgs, CurrentLocation); + if (!CallOp) + return; + + Invoker = InstantiateFunctionDeclaration( + Invoker->getDescribedFunctionTemplate(), TemplateArgs, CurrentLocation); + if (!Invoker) + return; } + if (CallOp->isInvalidDecl()) + return; + // Mark the call operator referenced (and add to pending instantiations // if necessary). // For both the conversion and static-invoker template specializations @@ -12246,39 +12635,24 @@ void Sema::DefineImplicitLambdaToFunctionPointerConversion( // to the PendingInstantiations. MarkFunctionReferenced(CurrentLocation, CallOp); - // Retrieve the static invoker... - CXXMethodDecl *Invoker = Lambda->getLambdaStaticInvoker(); - // ... and get the corresponding specialization for a generic lambda. - if (Lambda->isGenericLambda()) { - assert(DeducedTemplateArgs && - "Must have deduced template arguments from Conversion Operator"); - FunctionTemplateDecl *InvokeTemplate = - Invoker->getDescribedFunctionTemplate(); - void *InsertPos = nullptr; - FunctionDecl *InvokeSpec = InvokeTemplate->findSpecialization( - DeducedTemplateArgs->asArray(), - InsertPos); - assert(InvokeSpec && - "Must have a corresponding static invoker specialization"); - Invoker = cast<CXXMethodDecl>(InvokeSpec); - } + // Fill in the __invoke function with a dummy implementation. IR generation + // will fill in the actual details. Update its type in case it contained + // an 'auto'. + Invoker->markUsed(Context); + Invoker->setReferenced(); + Invoker->setType(Conv->getReturnType()->getPointeeType()); + Invoker->setBody(new (Context) CompoundStmt(Conv->getLocation())); + // Construct the body of the conversion function { return __invoke; }. Expr *FunctionRef = BuildDeclRefExpr(Invoker, Invoker->getType(), - VK_LValue, Conv->getLocation()).get(); + VK_LValue, Conv->getLocation()).get(); assert(FunctionRef && "Can't refer to __invoke function?"); Stmt *Return = BuildReturnStmt(Conv->getLocation(), FunctionRef).get(); Conv->setBody(CompoundStmt::Create(Context, Return, Conv->getLocation(), Conv->getLocation())); - Conv->markUsed(Context); Conv->setReferenced(); - // Fill in the __invoke function with a dummy implementation. IR generation - // will fill in the actual details. - Invoker->markUsed(Context); - Invoker->setReferenced(); - Invoker->setBody(new (Context) CompoundStmt(Conv->getLocation())); - if (ASTMutationListener *L = getASTMutationListener()) { L->CompletedImplicitDefinition(Conv); L->CompletedImplicitDefinition(Invoker); @@ -12339,7 +12713,7 @@ void Sema::DefineImplicitLambdaToBlockPointerConversion( } } -/// \brief Determine whether the given list arguments contains exactly one +/// Determine whether the given list arguments contains exactly one /// "real" (non-default) argument. static bool hasOneRealArgument(MultiExprArg Args) { switch (Args.size()) { @@ -12550,7 +12924,7 @@ void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) { Diag(VD->getLocation(), diag::warn_global_destructor); } -/// \brief Given a constructor and the set of arguments provided for the +/// 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. /// @@ -12617,6 +12991,13 @@ CheckOperatorNewDeleteDeclarationScope(Sema &SemaRef, return false; } +static QualType +RemoveAddressSpaceFromPtr(Sema &SemaRef, const PointerType *PtrTy) { + QualType QTy = PtrTy->getPointeeType(); + QTy = SemaRef.Context.removeAddrSpaceQualType(QTy); + return SemaRef.Context.getPointerType(QTy); +} + static inline bool CheckOperatorNewDeleteTypes(Sema &SemaRef, const FunctionDecl *FnDecl, CanQualType ExpectedResultType, @@ -12632,6 +13013,13 @@ CheckOperatorNewDeleteTypes(Sema &SemaRef, const FunctionDecl *FnDecl, diag::err_operator_new_delete_dependent_result_type) << FnDecl->getDeclName() << ExpectedResultType; + // OpenCL C++: the operator is valid on any address space. + if (SemaRef.getLangOpts().OpenCLCPlusPlus) { + if (auto *PtrTy = ResultType->getAs<PointerType>()) { + ResultType = RemoveAddressSpaceFromPtr(SemaRef, PtrTy); + } + } + // Check that the result type is what we expect. if (SemaRef.Context.getCanonicalType(ResultType) != ExpectedResultType) return SemaRef.Diag(FnDecl->getLocation(), @@ -12657,6 +13045,13 @@ CheckOperatorNewDeleteTypes(Sema &SemaRef, const FunctionDecl *FnDecl, << FnDecl->getDeclName() << ExpectedFirstParamType; // Check that the first parameter type is what we expect. + if (SemaRef.getLangOpts().OpenCLCPlusPlus) { + // OpenCL C++: the operator is valid on any address space. + if (auto *PtrTy = + FnDecl->getParamDecl(0)->getType()->getAs<PointerType>()) { + FirstParamType = RemoveAddressSpaceFromPtr(SemaRef, PtrTy); + } + } if (SemaRef.Context.getCanonicalType(FirstParamType).getUnqualifiedType() != ExpectedFirstParamType) return SemaRef.Diag(FnDecl->getLocation(), InvalidParamTypeDiag) @@ -12966,6 +13361,7 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) { ParamType->isSpecificBuiltinType(BuiltinType::LongDouble) || Context.hasSameType(ParamType, Context.CharTy) || Context.hasSameType(ParamType, Context.WideCharTy) || + Context.hasSameType(ParamType, Context.Char8Ty) || Context.hasSameType(ParamType, Context.Char16Ty) || Context.hasSameType(ParamType, Context.Char32Ty)) { } else if (const PointerType *Ptr = ParamType->getAs<PointerType>()) { @@ -13026,10 +13422,12 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) { } 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 + // Only const char *, const wchar_t*, const char8_t*, const char16_t*, and + // const char32_t* are allowed as the first parameter to a two-parameter + // function if (!(Context.hasSameType(InnerType, Context.CharTy) || Context.hasSameType(InnerType, Context.WideCharTy) || + Context.hasSameType(InnerType, Context.Char8Ty) || Context.hasSameType(InnerType, Context.Char16Ty) || Context.hasSameType(InnerType, Context.Char32Ty))) { Diag((*Param)->getSourceRange().getBegin(), @@ -13136,19 +13534,18 @@ Decl *Sema::ActOnFinishLinkageSpecification(Scope *S, } Decl *Sema::ActOnEmptyDeclaration(Scope *S, - AttributeList *AttrList, + const ParsedAttributesView &AttrList, SourceLocation SemiLoc) { Decl *ED = EmptyDecl::Create(Context, CurContext, SemiLoc); // Attribute declarations appertain to empty declaration so we handle // them here. - if (AttrList) - ProcessDeclAttributeList(S, ED, AttrList); + ProcessDeclAttributeList(S, ED, AttrList); CurContext->addDecl(ED); return ED; } -/// \brief Perform semantic analysis for the variable declaration that +/// Perform semantic analysis for the variable declaration that /// occurs within a C++ catch clause, returning the newly-created /// variable. VarDecl *Sema::BuildExceptionDeclaration(Scope *S, @@ -13404,7 +13801,7 @@ Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc, return Decl; } -/// \brief Perform semantic analysis of the given friend type declaration. +/// Perform semantic analysis of the given friend type declaration. /// /// \returns A friend declaration that. FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation LocStart, @@ -13481,10 +13878,9 @@ FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation LocStart, /// templated. Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, unsigned TagSpec, SourceLocation TagLoc, - CXXScopeSpec &SS, - IdentifierInfo *Name, + CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, - AttributeList *Attr, + const ParsedAttributesView &Attr, MultiTemplateParamsArg TempParamLists) { TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec); @@ -13597,7 +13993,6 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, return Friend; } - /// Handle a friend type declaration. This works in tandem with /// ActOnTag. /// @@ -13625,7 +14020,7 @@ Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, // Try to convert the decl specifier to a type. This works for // friend templates because ActOnTag never produces a ClassTemplateDecl // for a TUK_Friend. - Declarator TheDeclarator(DS, Declarator::MemberContext); + Declarator TheDeclarator(DS, DeclaratorContext::MemberContext); TypeSourceInfo *TSI = GetTypeForDeclarator(TheDeclarator, S); QualType T = TSI->getType(); if (TheDeclarator.isInvalidType()) @@ -13799,7 +14194,8 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, // elaborated-type-specifier, the lookup to determine whether // the entity has been previously declared shall not consider // any scopes outside the innermost enclosing namespace. - bool isTemplateId = D.getName().getKind() == UnqualifiedId::IK_TemplateId; + bool isTemplateId = + D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId; // Find the appropriate context according to the above. DC = CurContext; @@ -13910,24 +14306,24 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, if (!DC->isRecord()) { int DiagArg = -1; switch (D.getName().getKind()) { - case UnqualifiedId::IK_ConstructorTemplateId: - case UnqualifiedId::IK_ConstructorName: + case UnqualifiedIdKind::IK_ConstructorTemplateId: + case UnqualifiedIdKind::IK_ConstructorName: DiagArg = 0; break; - case UnqualifiedId::IK_DestructorName: + case UnqualifiedIdKind::IK_DestructorName: DiagArg = 1; break; - case UnqualifiedId::IK_ConversionFunctionId: + case UnqualifiedIdKind::IK_ConversionFunctionId: DiagArg = 2; break; - case UnqualifiedId::IK_DeductionGuideName: + case UnqualifiedIdKind::IK_DeductionGuideName: DiagArg = 3; break; - case UnqualifiedId::IK_Identifier: - case UnqualifiedId::IK_ImplicitSelfParam: - case UnqualifiedId::IK_LiteralOperatorId: - case UnqualifiedId::IK_OperatorFunctionId: - case UnqualifiedId::IK_TemplateId: + case UnqualifiedIdKind::IK_Identifier: + case UnqualifiedIdKind::IK_ImplicitSelfParam: + case UnqualifiedIdKind::IK_LiteralOperatorId: + case UnqualifiedIdKind::IK_OperatorFunctionId: + case UnqualifiedIdKind::IK_TemplateId: break; } // This implies that it has to be an operator or function. @@ -14168,6 +14564,16 @@ bool Sema::CheckOverridingFunctionAttributes(const CXXMethodDecl *New, } } + // Virtual overrides must have the same code_seg. + const auto *OldCSA = Old->getAttr<CodeSegAttr>(); + const auto *NewCSA = New->getAttr<CodeSegAttr>(); + if ((NewCSA || OldCSA) && + (!OldCSA || !NewCSA || NewCSA->getName() != OldCSA->getName())) { + Diag(New->getLocation(), diag::err_mismatched_code_seg_override); + Diag(Old->getLocation(), diag::note_previous_declaration); + return true; + } + CallingConv NewCC = NewFT->getCallConv(), OldCC = OldFT->getCallConv(); // If the calling conventions match, everything is fine @@ -14294,7 +14700,7 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, return false; } -/// \brief Mark the given method pure. +/// Mark the given method pure. /// /// \param Method the method to be marked pure. /// @@ -14324,7 +14730,7 @@ void Sema::ActOnPureSpecifier(Decl *D, SourceLocation ZeroLoc) { Diag(D->getLocation(), diag::err_illegal_initializer); } -/// \brief Determine whether the given declaration is a global variable or +/// Determine whether the given declaration is a global variable or /// static data member. static bool isNonlocalVariable(const Decl *D) { if (const VarDecl *Var = dyn_cast_or_null<VarDecl>(D)) @@ -14431,7 +14837,7 @@ void Sema::MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class, // Try to insert this class into the map. LoadExternalVTableUses(); - Class = cast<CXXRecordDecl>(Class->getCanonicalDecl()); + Class = Class->getCanonicalDecl(); std::pair<llvm::DenseMap<CXXRecordDecl *, bool>::iterator, bool> Pos = VTablesUsed.insert(std::make_pair(Class, DefinitionRequired)); if (!Pos.second) { @@ -14543,7 +14949,7 @@ bool Sema::DefineUsedVTables() { // vtable for this class is required. DefinedAnything = true; MarkVirtualMembersReferenced(Loc, Class); - CXXRecordDecl *Canonical = cast<CXXRecordDecl>(Class->getCanonicalDecl()); + CXXRecordDecl *Canonical = Class->getCanonicalDecl(); if (VTablesUsed[Canonical]) Consumer.HandleVTable(Class); @@ -14666,9 +15072,9 @@ void Sema::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) { static void DelegatingCycleHelper(CXXConstructorDecl* Ctor, - llvm::SmallSet<CXXConstructorDecl*, 4> &Valid, - llvm::SmallSet<CXXConstructorDecl*, 4> &Invalid, - llvm::SmallSet<CXXConstructorDecl*, 4> &Current, + llvm::SmallPtrSet<CXXConstructorDecl*, 4> &Valid, + llvm::SmallPtrSet<CXXConstructorDecl*, 4> &Invalid, + llvm::SmallPtrSet<CXXConstructorDecl*, 4> &Current, Sema &S) { if (Ctor->isInvalidDecl()) return; @@ -14730,7 +15136,7 @@ void DelegatingCycleHelper(CXXConstructorDecl* Ctor, void Sema::CheckDelegatingCtorCycles() { - llvm::SmallSet<CXXConstructorDecl*, 4> Valid, Invalid, Current; + llvm::SmallPtrSet<CXXConstructorDecl*, 4> Valid, Invalid, Current; for (DelegatingCtorDeclsType::iterator I = DelegatingCtorDecls.begin(ExternalSource), @@ -14738,14 +15144,12 @@ void Sema::CheckDelegatingCtorCycles() { I != E; ++I) DelegatingCycleHelper(*I, Valid, Invalid, Current, *this); - for (llvm::SmallSet<CXXConstructorDecl *, 4>::iterator CI = Invalid.begin(), - CE = Invalid.end(); - CI != CE; ++CI) + for (auto CI = Invalid.begin(), CE = Invalid.end(); CI != CE; ++CI) (*CI)->setInvalidDecl(); } namespace { - /// \brief AST visitor that finds references to the 'this' expression. + /// AST visitor that finds references to the 'this' expression. class FindCXXThisExpr : public RecursiveASTVisitor<FindCXXThisExpr> { Sema &S; @@ -14815,7 +15219,9 @@ bool Sema::checkThisInStaticMemberFunctionExceptionSpec(CXXMethodDecl *Method) { case EST_None: break; - case EST_ComputedNoexcept: + case EST_DependentNoexcept: + case EST_NoexceptFalse: + case EST_NoexceptTrue: if (!Finder.TraverseStmt(Proto->getNoexceptExpr())) return true; LLVM_FALLTHROUGH; @@ -14912,31 +15318,17 @@ void Sema::checkExceptionSpecification( return; } - if (EST == EST_ComputedNoexcept) { - // If an error occurred, there's no expression here. - if (NoexceptExpr) { - assert((NoexceptExpr->isTypeDependent() || - NoexceptExpr->getType()->getCanonicalTypeUnqualified() == - Context.BoolTy) && - "Parser should have made sure that the expression is boolean"); - if (IsTopLevel && NoexceptExpr && - DiagnoseUnexpandedParameterPack(NoexceptExpr)) { - ESI.Type = EST_BasicNoexcept; - return; - } - - if (!NoexceptExpr->isValueDependent()) { - ExprResult Result = VerifyIntegerConstantExpression( - NoexceptExpr, nullptr, diag::err_noexcept_needs_constant_expression, - /*AllowFold*/ false); - if (Result.isInvalid()) { - ESI.Type = EST_BasicNoexcept; - return; - } - NoexceptExpr = Result.get(); - } - ESI.NoexceptExpr = NoexceptExpr; + if (isComputedNoexcept(EST)) { + assert((NoexceptExpr->isTypeDependent() || + NoexceptExpr->getType()->getCanonicalTypeUnqualified() == + Context.BoolTy) && + "Parser should have made sure that the expression is boolean"); + if (IsTopLevel && DiagnoseUnexpandedParameterPack(NoexceptExpr)) { + ESI.Type = EST_BasicNoexcept; + return; } + + ESI.NoexceptExpr = NoexceptExpr; return; } } @@ -14981,11 +15373,11 @@ void Sema::actOnDelayedExceptionSpecification(Decl *MethodD, /// HandleMSProperty - Analyze a __delcspec(property) field of a C++ class. /// MSPropertyDecl *Sema::HandleMSProperty(Scope *S, RecordDecl *Record, - SourceLocation DeclStart, - Declarator &D, Expr *BitWidth, + SourceLocation DeclStart, Declarator &D, + Expr *BitWidth, InClassInitStyle InitStyle, AccessSpecifier AS, - AttributeList *MSPropertyAttr) { + const ParsedAttr &MSPropertyAttr) { IdentifierInfo *II = D.getIdentifier(); if (!II) { Diag(DeclStart, diag::err_anonymous_property); @@ -15048,7 +15440,7 @@ MSPropertyDecl *Sema::HandleMSProperty(Scope *S, RecordDecl *Record, PrevDecl = nullptr; SourceLocation TSSL = D.getLocStart(); - const AttributeList::PropertyData &Data = MSPropertyAttr->getPropertyData(); + const ParsedAttr::PropertyData &Data = MSPropertyAttr.getPropertyData(); MSPropertyDecl *NewPD = MSPropertyDecl::Create( Context, Record, Loc, II, T, TInfo, TSSL, Data.GetterId, Data.SetterId); ProcessDeclAttributes(TUScope, NewPD, D); |