diff options
Diffstat (limited to 'clang/lib/Sema/SemaDeclCXX.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 380 |
1 files changed, 226 insertions, 154 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 83c97626ff7e..20410a959cd0 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -26,6 +26,7 @@ #include "clang/AST/TypeOrdering.h" #include "clang/Basic/AttributeCommonInfo.h" #include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/Specifiers.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/LiteralSupport.h" #include "clang/Lex/Preprocessor.h" @@ -435,7 +436,7 @@ void Sema::CheckExtraCXXDefaultArguments(Declarator &D) { } static bool functionDeclHasDefaultArgument(const FunctionDecl *FD) { - return std::any_of(FD->param_begin(), FD->param_end(), [](ParmVarDecl *P) { + return llvm::any_of(FD->parameters(), [](ParmVarDecl *P) { return P->hasDefaultArg() && !P->hasInheritedDefaultArg(); }); } @@ -983,9 +984,9 @@ static std::string printTemplateArgs(const PrintingPolicy &PrintingPolicy, for (auto &Arg : Args.arguments()) { if (!First) OS << ", "; - Arg.getArgument().print( - PrintingPolicy, OS, - TemplateParameterList::shouldIncludeTypeForArgument(Params, I)); + Arg.getArgument().print(PrintingPolicy, OS, + TemplateParameterList::shouldIncludeTypeForArgument( + PrintingPolicy, Params, I)); First = false; I++; } @@ -1383,9 +1384,8 @@ static bool checkMemberDecomposition(Sema &S, ArrayRef<BindingDecl*> Bindings, DecompType.getQualifiers()); auto DiagnoseBadNumberOfBindings = [&]() -> bool { - unsigned NumFields = - std::count_if(RD->field_begin(), RD->field_end(), - [](FieldDecl *FD) { return !FD->isUnnamedBitfield(); }); + unsigned NumFields = llvm::count_if( + RD->fields(), [](FieldDecl *FD) { return !FD->isUnnamedBitfield(); }); assert(Bindings.size() != NumFields); S.Diag(Src->getLocation(), diag::err_decomp_decl_wrong_number_bindings) << DecompType << (unsigned)Bindings.size() << NumFields << NumFields @@ -2050,6 +2050,13 @@ CheckConstexprFunctionStmt(Sema &SemaRef, const FunctionDecl *Dcl, Stmt *S, ReturnStmts.push_back(S->getBeginLoc()); return true; + case Stmt::AttributedStmtClass: + // Attributes on a statement don't affect its formal kind and hence don't + // affect its validity in a constexpr function. + return CheckConstexprFunctionStmt(SemaRef, Dcl, + cast<AttributedStmt>(S)->getSubStmt(), + ReturnStmts, Cxx1yLoc, Cxx2aLoc, Kind); + case Stmt::CompoundStmtClass: { // C++1y allows compound-statements. if (!Cxx1yLoc.isValid()) @@ -2064,11 +2071,6 @@ CheckConstexprFunctionStmt(Sema &SemaRef, const FunctionDecl *Dcl, Stmt *S, return true; } - case Stmt::AttributedStmtClass: - if (!Cxx1yLoc.isValid()) - Cxx1yLoc = S->getBeginLoc(); - return true; - case Stmt::IfStmtClass: { // C++1y allows if-statements. if (!Cxx1yLoc.isValid()) @@ -2727,6 +2729,8 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, KnownBase = Bases[idx]; Bases[NumGoodBases++] = Bases[idx]; + if (NewBaseType->isDependentType()) + continue; // Note this base's direct & indirect bases, if there could be ambiguity. if (Bases.size() > 1) NoteIndirectBases(Context, IndirectBaseTypes, NewBaseType); @@ -3581,9 +3585,8 @@ namespace { llvm::SmallVector<unsigned, 4> UsedFieldIndex; // Discard the first field since it is the field decl that is being // initialized. - for (auto I = Fields.rbegin() + 1, E = Fields.rend(); I != E; ++I) { - UsedFieldIndex.push_back((*I)->getFieldIndex()); - } + for (const FieldDecl *FD : llvm::drop_begin(llvm::reverse(Fields))) + UsedFieldIndex.push_back(FD->getFieldIndex()); for (auto UsedIter = UsedFieldIndex.begin(), UsedEnd = UsedFieldIndex.end(), @@ -4114,7 +4117,7 @@ Sema::ActOnMemInitializer(Decl *ConstructorD, namespace { // Callback to only accept typo corrections that can be a valid C++ member -// intializer: either a non-static field member or a base class. +// initializer: either a non-static field member or a base class. class MemInitializerValidatorCCC final : public CorrectionCandidateCallback { public: explicit MemInitializerValidatorCCC(CXXRecordDecl *ClassDecl) @@ -4162,7 +4165,8 @@ Sema::BuildMemInitializer(Decl *ConstructorD, SourceLocation IdLoc, Expr *Init, SourceLocation EllipsisLoc) { - ExprResult Res = CorrectDelayedTyposInExpr(Init); + ExprResult Res = CorrectDelayedTyposInExpr(Init, /*InitDecl=*/nullptr, + /*RecoverUncorrectedTypos=*/true); if (!Res.isUsable()) return true; Init = Res.get(); @@ -4214,7 +4218,7 @@ Sema::BuildMemInitializer(Decl *ConstructorD, if (BaseType.isNull()) return true; } else if (DS.getTypeSpecType() == TST_decltype) { - BaseType = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc()); + BaseType = BuildDecltypeType(DS.getRepAsExpr()); } else if (DS.getTypeSpecType() == TST_decltype_auto) { Diag(DS.getTypeSpecTypeLoc(), diag::err_decltype_auto_invalid); return true; @@ -4375,18 +4379,25 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init, InitializationSequence InitSeq(*this, MemberEntity, Kind, Args); ExprResult MemberInit = InitSeq.Perform(*this, MemberEntity, Kind, Args, nullptr); - if (MemberInit.isInvalid()) - return true; - - // C++11 [class.base.init]p7: - // The initialization of each base and member constitutes a - // full-expression. - MemberInit = ActOnFinishFullExpr(MemberInit.get(), InitRange.getBegin(), - /*DiscardedValue*/ false); - if (MemberInit.isInvalid()) - return true; + if (!MemberInit.isInvalid()) { + // C++11 [class.base.init]p7: + // The initialization of each base and member constitutes a + // full-expression. + MemberInit = ActOnFinishFullExpr(MemberInit.get(), InitRange.getBegin(), + /*DiscardedValue*/ false); + } - Init = MemberInit.get(); + if (MemberInit.isInvalid()) { + // Args were sensible expressions but we couldn't initialize the member + // from them. Preserve them in a RecoveryExpr instead. + Init = CreateRecoveryExpr(InitRange.getBegin(), InitRange.getEnd(), Args, + Member->getType()) + .get(); + if (!Init) + return true; + } else { + Init = MemberInit.get(); + } } if (DirectMember) { @@ -4428,29 +4439,35 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init, InitializationSequence InitSeq(*this, DelegationEntity, Kind, Args); ExprResult DelegationInit = InitSeq.Perform(*this, DelegationEntity, Kind, Args, nullptr); - if (DelegationInit.isInvalid()) - return true; - - assert(cast<CXXConstructExpr>(DelegationInit.get())->getConstructor() && - "Delegating constructor with no target?"); + if (!DelegationInit.isInvalid()) { + assert((DelegationInit.get()->containsErrors() || + cast<CXXConstructExpr>(DelegationInit.get())->getConstructor()) && + "Delegating constructor with no target?"); - // C++11 [class.base.init]p7: - // The initialization of each base and member constitutes a - // full-expression. - DelegationInit = ActOnFinishFullExpr( - DelegationInit.get(), InitRange.getBegin(), /*DiscardedValue*/ false); - if (DelegationInit.isInvalid()) - return true; + // C++11 [class.base.init]p7: + // The initialization of each base and member constitutes a + // full-expression. + DelegationInit = ActOnFinishFullExpr( + DelegationInit.get(), InitRange.getBegin(), /*DiscardedValue*/ false); + } - // If we are in a dependent context, template instantiation will - // perform this type-checking again. Just save the arguments that we - // received in a ParenListExpr. - // FIXME: This isn't quite ideal, since our ASTs don't capture all - // of the information that we have about the base - // initializer. However, deconstructing the ASTs is a dicey process, - // and this approach is far more likely to get the corner cases right. - if (CurContext->isDependentContext()) - DelegationInit = Init; + if (DelegationInit.isInvalid()) { + DelegationInit = + CreateRecoveryExpr(InitRange.getBegin(), InitRange.getEnd(), Args, + QualType(ClassDecl->getTypeForDecl(), 0)); + if (DelegationInit.isInvalid()) + return true; + } else { + // If we are in a dependent context, template instantiation will + // perform this type-checking again. Just save the arguments that we + // received in a ParenListExpr. + // FIXME: This isn't quite ideal, since our ASTs don't capture all + // of the information that we have about the base + // initializer. However, deconstructing the ASTs is a dicey process, + // and this approach is far more likely to get the corner cases right. + if (CurContext->isDependentContext()) + DelegationInit = Init; + } return new (Context) CXXCtorInitializer(Context, TInfo, InitRange.getBegin(), DelegationInit.getAs<Expr>(), @@ -4474,7 +4491,12 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, // of that class, the mem-initializer is ill-formed. A // mem-initializer-list can initialize a base class using any // name that denotes that base class type. - bool Dependent = BaseType->isDependentType() || Init->isTypeDependent(); + + // We can store the initializers in "as-written" form and delay analysis until + // instantiation if the constructor is dependent. But not for dependent + // (broken) code in a non-template! SetCtorInitializers does not expect this. + bool Dependent = CurContext->isDependentContext() && + (BaseType->isDependentType() || Init->isTypeDependent()); SourceRange InitRange = Init->getSourceRange(); if (EllipsisLoc.isValid()) { @@ -4561,26 +4583,30 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, InitRange.getEnd()); InitializationSequence InitSeq(*this, BaseEntity, Kind, Args); ExprResult BaseInit = InitSeq.Perform(*this, BaseEntity, Kind, Args, nullptr); - if (BaseInit.isInvalid()) - return true; - - // C++11 [class.base.init]p7: - // The initialization of each base and member constitutes a - // full-expression. - BaseInit = ActOnFinishFullExpr(BaseInit.get(), InitRange.getBegin(), - /*DiscardedValue*/ false); - if (BaseInit.isInvalid()) - return true; + if (!BaseInit.isInvalid()) { + // C++11 [class.base.init]p7: + // The initialization of each base and member constitutes a + // full-expression. + BaseInit = ActOnFinishFullExpr(BaseInit.get(), InitRange.getBegin(), + /*DiscardedValue*/ false); + } - // If we are in a dependent context, template instantiation will - // perform this type-checking again. Just save the arguments that we - // received in a ParenListExpr. - // FIXME: This isn't quite ideal, since our ASTs don't capture all - // of the information that we have about the base - // initializer. However, deconstructing the ASTs is a dicey process, - // and this approach is far more likely to get the corner cases right. - if (CurContext->isDependentContext()) - BaseInit = Init; + if (BaseInit.isInvalid()) { + BaseInit = CreateRecoveryExpr(InitRange.getBegin(), InitRange.getEnd(), + Args, BaseType); + if (BaseInit.isInvalid()) + return true; + } else { + // If we are in a dependent context, template instantiation will + // perform this type-checking again. Just save the arguments that we + // received in a ParenListExpr. + // FIXME: This isn't quite ideal, since our ASTs don't capture all + // of the information that we have about the base + // initializer. However, deconstructing the ASTs is a dicey process, + // and this approach is far more likely to get the corner cases right. + if (CurContext->isDependentContext()) + BaseInit = Init; + } return new (Context) CXXCtorInitializer(Context, BaseTInfo, BaseSpec->isVirtual(), @@ -5859,6 +5885,7 @@ struct CheckAbstractUsage { if (CT != Info.AbstractType) return; // It matched; do some magic. + // FIXME: These should be at most warnings. See P0929R2, CWG1640, CWG1646. if (Sel == Sema::AbstractArrayType) { Info.S.Diag(Ctx->getLocation(), diag::err_array_of_abstract_type) << T << TL.getSourceRange(); @@ -5877,19 +5904,31 @@ void AbstractUsageInfo::CheckType(const NamedDecl *D, TypeLoc TL, } -/// Check for invalid uses of an abstract type in a method declaration. +/// Check for invalid uses of an abstract type in a function declaration. static void CheckAbstractClassUsage(AbstractUsageInfo &Info, - CXXMethodDecl *MD) { + FunctionDecl *FD) { // No need to do the check on definitions, which require that // the return/param types be complete. - if (MD->doesThisDeclarationHaveABody()) + if (FD->doesThisDeclarationHaveABody()) return; // For safety's sake, just ignore it if we don't have type source // information. This should never happen for non-implicit methods, // but... - if (TypeSourceInfo *TSI = MD->getTypeSourceInfo()) - Info.CheckType(MD, TSI->getTypeLoc(), Sema::AbstractNone); + if (TypeSourceInfo *TSI = FD->getTypeSourceInfo()) + Info.CheckType(FD, TSI->getTypeLoc(), Sema::AbstractNone); +} + +/// Check for invalid uses of an abstract type in a variable0 declaration. +static void CheckAbstractClassUsage(AbstractUsageInfo &Info, + VarDecl *VD) { + // No need to do the check on definitions, which require that + // the type is complete. + if (VD->isThisDeclarationADefinition()) + return; + + Info.CheckType(VD, VD->getTypeSourceInfo()->getTypeLoc(), + Sema::AbstractVariableType); } /// Check for invalid uses of an abstract type within a class definition. @@ -5898,29 +5937,32 @@ static void CheckAbstractClassUsage(AbstractUsageInfo &Info, for (auto *D : RD->decls()) { if (D->isImplicit()) continue; - // Methods and method templates. - if (isa<CXXMethodDecl>(D)) { - CheckAbstractClassUsage(Info, cast<CXXMethodDecl>(D)); - } else if (isa<FunctionTemplateDecl>(D)) { - FunctionDecl *FD = cast<FunctionTemplateDecl>(D)->getTemplatedDecl(); - CheckAbstractClassUsage(Info, cast<CXXMethodDecl>(FD)); + // Step through friends to the befriended declaration. + if (auto *FD = dyn_cast<FriendDecl>(D)) { + D = FD->getFriendDecl(); + if (!D) continue; + } + + // Functions and function templates. + if (auto *FD = dyn_cast<FunctionDecl>(D)) { + CheckAbstractClassUsage(Info, FD); + } else if (auto *FTD = dyn_cast<FunctionTemplateDecl>(D)) { + CheckAbstractClassUsage(Info, FTD->getTemplatedDecl()); // Fields and static variables. - } else if (isa<FieldDecl>(D)) { - FieldDecl *FD = cast<FieldDecl>(D); + } else if (auto *FD = dyn_cast<FieldDecl>(D)) { if (TypeSourceInfo *TSI = FD->getTypeSourceInfo()) Info.CheckType(FD, TSI->getTypeLoc(), Sema::AbstractFieldType); - } else if (isa<VarDecl>(D)) { - VarDecl *VD = cast<VarDecl>(D); - if (TypeSourceInfo *TSI = VD->getTypeSourceInfo()) - Info.CheckType(VD, TSI->getTypeLoc(), Sema::AbstractVariableType); + } else if (auto *VD = dyn_cast<VarDecl>(D)) { + CheckAbstractClassUsage(Info, VD); + } else if (auto *VTD = dyn_cast<VarTemplateDecl>(D)) { + CheckAbstractClassUsage(Info, VTD->getTemplatedDecl()); // Nested classes and class templates. - } else if (isa<CXXRecordDecl>(D)) { - CheckAbstractClassUsage(Info, cast<CXXRecordDecl>(D)); - } else if (isa<ClassTemplateDecl>(D)) { - CheckAbstractClassUsage(Info, - cast<ClassTemplateDecl>(D)->getTemplatedDecl()); + } else if (auto *RD = dyn_cast<CXXRecordDecl>(D)) { + CheckAbstractClassUsage(Info, RD); + } else if (auto *CTD = dyn_cast<ClassTemplateDecl>(D)) { + CheckAbstractClassUsage(Info, CTD->getTemplatedDecl()); } } } @@ -5960,11 +6002,14 @@ static void ReferenceDllExportedMembers(Sema &S, CXXRecordDecl *Class) { S.MarkVTableUsed(Class->getLocation(), Class, true); for (Decl *Member : Class->decls()) { + // Skip members that were not marked exported. + if (!Member->hasAttr<DLLExportAttr>()) + continue; + // 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 && + if (VD && VD->getStorageClass() == SC_Static && TSK == TSK_ImplicitInstantiation) S.MarkVariableReferenced(VD->getLocation(), VD); @@ -5972,40 +6017,47 @@ static void ReferenceDllExportedMembers(Sema &S, CXXRecordDecl *Class) { if (!MD) continue; - if (Member->getAttr<DLLExportAttr>()) { - if (MD->isUserProvided()) { - // Instantiate non-default class member functions ... + if (MD->isUserProvided()) { + // Instantiate non-default class member functions ... - // .. except for certain kinds of template specializations. - if (TSK == TSK_ImplicitInstantiation && !ClassAttr->isInherited()) - continue; + // .. except for certain kinds of template specializations. + if (TSK == TSK_ImplicitInstantiation && !ClassAttr->isInherited()) + continue; - S.MarkFunctionReferenced(Class->getLocation(), MD); + // If this is an MS ABI dllexport default constructor, instantiate any + // default arguments. + if (S.Context.getTargetInfo().getCXXABI().isMicrosoft()) { + auto *CD = dyn_cast<CXXConstructorDecl>(MD); + if (CD && CD->isDefaultConstructor() && TSK == TSK_Undeclared) { + S.InstantiateDefaultCtorDefaultArgs(CD); + } + } - // The function will be passed to the consumer when its definition is - // encountered. - } else if (MD->isExplicitlyDefaulted()) { - // Synthesize and instantiate explicitly defaulted methods. - S.MarkFunctionReferenced(Class->getLocation(), MD); + S.MarkFunctionReferenced(Class->getLocation(), MD); - if (TSK != TSK_ExplicitInstantiationDefinition) { - // Except for explicit instantiation defs, we will not see the - // definition again later, so pass it to the consumer now. - S.Consumer.HandleTopLevelDecl(DeclGroupRef(MD)); - } - } else if (!MD->isTrivial() || - MD->isCopyAssignmentOperator() || - MD->isMoveAssignmentOperator()) { - // Synthesize and instantiate non-trivial implicit methods, and the copy - // and move assignment operators. The latter are exported even if they - // are trivial, because the address of an operator can be taken and - // should compare equal across libraries. - S.MarkFunctionReferenced(Class->getLocation(), MD); + // The function will be passed to the consumer when its definition is + // encountered. + } else if (MD->isExplicitlyDefaulted()) { + // Synthesize and instantiate explicitly defaulted methods. + S.MarkFunctionReferenced(Class->getLocation(), MD); - // There is no later point when we will see the definition of this - // function, so pass it to the consumer now. + if (TSK != TSK_ExplicitInstantiationDefinition) { + // Except for explicit instantiation defs, we will not see the + // definition again later, so pass it to the consumer now. S.Consumer.HandleTopLevelDecl(DeclGroupRef(MD)); } + } else if (!MD->isTrivial() || + MD->isCopyAssignmentOperator() || + MD->isMoveAssignmentOperator()) { + // Synthesize and instantiate non-trivial implicit methods, and the copy + // and move assignment operators. The latter are exported even if they + // are trivial, because the address of an operator can be taken and + // should compare equal across libraries. + S.MarkFunctionReferenced(Class->getLocation(), MD); + + // There is no later point when we will see the definition of this + // function, so pass it to the consumer now. + S.Consumer.HandleTopLevelDecl(DeclGroupRef(MD)); } } } @@ -7771,9 +7823,21 @@ private: DCK == DefaultedComparisonKind::Relational) && !Best->RewriteKind) { if (Diagnose == ExplainDeleted) { - S.Diag(Best->Function->getLocation(), - diag::note_defaulted_comparison_not_rewritten_callee) - << FD; + if (Best->Function) { + S.Diag(Best->Function->getLocation(), + diag::note_defaulted_comparison_not_rewritten_callee) + << FD; + } else { + assert(Best->Conversions.size() == 2 && + Best->Conversions[0].isUserDefined() && + "non-user-defined conversion from class to built-in " + "comparison"); + S.Diag(Best->Conversions[0] + .UserDefined.FoundConversionFunction.getDecl() + ->getLocation(), + diag::note_defaulted_comparison_not_rewritten_conversion) + << FD; + } } return Result::deleted(); } @@ -7929,7 +7993,7 @@ private: if (Diagnose == ExplainDeleted) { S.Diag(Subobj.Loc, diag::note_defaulted_comparison_no_viable_function) - << FD << Subobj.Kind << Subobj.Decl; + << FD << (OO == OO_ExclaimEqual) << Subobj.Kind << Subobj.Decl; // For a three-way comparison, list both the candidates for the // original operator and the candidates for the synthesized operator. @@ -8157,7 +8221,7 @@ private: if (ReturnFalse.isInvalid()) return StmtError(); - return S.ActOnIfStmt(Loc, false, Loc, nullptr, + return S.ActOnIfStmt(Loc, IfStatementKind::Ordinary, Loc, nullptr, S.ActOnCondition(nullptr, Loc, NotCond.get(), Sema::ConditionKind::Boolean), Loc, ReturnFalse.get(), SourceLocation(), nullptr); @@ -8312,8 +8376,8 @@ private: return StmtError(); // if (...) - return S.ActOnIfStmt(Loc, /*IsConstexpr=*/false, Loc, InitStmt, Cond, Loc, - ReturnStmt.get(), + return S.ActOnIfStmt(Loc, IfStatementKind::Ordinary, Loc, InitStmt, Cond, + Loc, ReturnStmt.get(), /*ElseLoc=*/SourceLocation(), /*Else=*/nullptr); } @@ -9778,7 +9842,7 @@ public: }; } // end anonymous namespace -/// Add the most overriden methods from MD to Methods +/// Add the most overridden methods from MD to Methods static void AddMostOverridenMethods(const CXXMethodDecl *MD, llvm::SmallPtrSetImpl<const CXXMethodDecl *>& Methods) { if (MD->size_overridden_methods() == 0) @@ -12472,6 +12536,8 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc, return false; } + const NestedNameSpecifier *CNNS = + Context.getCanonicalNestedNameSpecifier(Qual); for (LookupResult::iterator I = Prev.begin(), E = Prev.end(); I != E; ++I) { NamedDecl *D = *I; @@ -12497,8 +12563,7 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc, // using decls differ if they name different scopes (but note that // template instantiation can cause this check to trigger when it // didn't before instantiation). - if (Context.getCanonicalNestedNameSpecifier(Qual) != - Context.getCanonicalNestedNameSpecifier(DQual)) + if (CNNS != Context.getCanonicalNestedNameSpecifier(DQual)) continue; Diag(NameLoc, diag::err_using_decl_redeclaration) << SS.getRange(); @@ -13234,6 +13299,7 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( CXXConstructorDecl *DefaultCon = CXXConstructorDecl::Create( Context, ClassDecl, ClassLoc, NameInfo, /*Type*/ QualType(), /*TInfo=*/nullptr, ExplicitSpecifier(), + getCurFPFeatures().isFPConstrained(), /*isInline=*/true, /*isImplicitlyDeclared=*/true, Constexpr ? ConstexprSpecKind::Constexpr : ConstexprSpecKind::Unspecified); @@ -13355,7 +13421,8 @@ Sema::findInheritingConstructor(SourceLocation Loc, CXXConstructorDecl *DerivedCtor = CXXConstructorDecl::Create( Context, Derived, UsingLoc, NameInfo, TInfo->getType(), TInfo, - BaseCtor->getExplicitSpecifier(), /*isInline=*/true, + BaseCtor->getExplicitSpecifier(), getCurFPFeatures().isFPConstrained(), + /*isInline=*/true, /*isImplicitlyDeclared=*/true, Constexpr ? BaseCtor->getConstexprKind() : ConstexprSpecKind::Unspecified, InheritedConstructor(Shadow, BaseCtor), @@ -13510,12 +13577,13 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) { DeclarationName Name = Context.DeclarationNames.getCXXDestructorName(ClassType); DeclarationNameInfo NameInfo(Name, ClassLoc); - CXXDestructorDecl *Destructor = - CXXDestructorDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, - QualType(), nullptr, /*isInline=*/true, - /*isImplicitlyDeclared=*/true, - Constexpr ? ConstexprSpecKind::Constexpr - : ConstexprSpecKind::Unspecified); + CXXDestructorDecl *Destructor = CXXDestructorDecl::Create( + Context, ClassDecl, ClassLoc, NameInfo, QualType(), nullptr, + getCurFPFeatures().isFPConstrained(), + /*isInline=*/true, + /*isImplicitlyDeclared=*/true, + Constexpr ? ConstexprSpecKind::Constexpr + : ConstexprSpecKind::Unspecified); Destructor->setAccess(AS_public); Destructor->setDefaulted(); @@ -14151,6 +14219,7 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { CXXMethodDecl *CopyAssignment = CXXMethodDecl::Create( Context, ClassDecl, ClassLoc, NameInfo, QualType(), /*TInfo=*/nullptr, /*StorageClass=*/SC_None, + getCurFPFeatures().isFPConstrained(), /*isInline=*/true, Constexpr ? ConstexprSpecKind::Constexpr : ConstexprSpecKind::Unspecified, SourceLocation()); @@ -14485,6 +14554,7 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) { CXXMethodDecl *MoveAssignment = CXXMethodDecl::Create( Context, ClassDecl, ClassLoc, NameInfo, QualType(), /*TInfo=*/nullptr, /*StorageClass=*/SC_None, + getCurFPFeatures().isFPConstrained(), /*isInline=*/true, Constexpr ? ConstexprSpecKind::Constexpr : ConstexprSpecKind::Unspecified, SourceLocation()); @@ -14864,7 +14934,7 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( // member of its class. CXXConstructorDecl *CopyConstructor = CXXConstructorDecl::Create( Context, ClassDecl, ClassLoc, NameInfo, QualType(), /*TInfo=*/nullptr, - ExplicitSpecifier(), + ExplicitSpecifier(), getCurFPFeatures().isFPConstrained(), /*isInline=*/true, /*isImplicitlyDeclared=*/true, Constexpr ? ConstexprSpecKind::Constexpr @@ -15004,7 +15074,7 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor( // member of its class. CXXConstructorDecl *MoveConstructor = CXXConstructorDecl::Create( Context, ClassDecl, ClassLoc, NameInfo, QualType(), /*TInfo=*/nullptr, - ExplicitSpecifier(), + ExplicitSpecifier(), getCurFPFeatures().isFPConstrained(), /*isInline=*/true, /*isImplicitlyDeclared=*/true, Constexpr ? ConstexprSpecKind::Constexpr @@ -15261,8 +15331,17 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, // can be omitted by constructing the temporary object // directly into the target of the omitted copy/move if (ConstructKind == CXXConstructExpr::CK_Complete && Constructor && + // FIXME: Converting constructors should also be accepted. + // But to fix this, the logic that digs down into a CXXConstructExpr + // to find the source object needs to handle it. + // Right now it assumes the source object is passed directly as the + // first argument. Constructor->isCopyOrMoveConstructor() && hasOneRealArgument(ExprArgs)) { Expr *SubExpr = ExprArgs[0]; + // FIXME: Per above, this is also incorrect if we want to accept + // converting constructors, as isTemporaryObject will + // reject temporaries with different type from the + // CXXRecord itself. Elidable = SubExpr->isTemporaryObject( Context, cast<CXXRecordDecl>(FoundDecl->getDeclContext())); } @@ -15400,7 +15479,7 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) { if (VD->isInvalidDecl()) return; // If initializing the variable failed, don't also diagnose problems with - // the desctructor, they're likely related. + // the destructor, they're likely related. if (VD->getInit() && VD->getInit()->containsErrors()) return; @@ -15830,7 +15909,7 @@ checkLiteralOperatorTemplateParameterList(Sema &SemaRef, // // As a DR resolution, we also allow placeholders for deduced class // template specializations. - if (SemaRef.getLangOpts().CPlusPlus20 && + if (SemaRef.getLangOpts().CPlusPlus20 && PmDecl && !PmDecl->isTemplateParameterPack() && (PmDecl->getType()->isRecordType() || PmDecl->getType()->getAs<DeducedTemplateSpecializationType>())) @@ -16806,10 +16885,7 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, while (DC->isRecord()) DC = DC->getParent(); - DeclContext *LookupDC = DC; - while (LookupDC->isTransparentContext()) - LookupDC = LookupDC->getParent(); - + DeclContext *LookupDC = DC->getNonTransparentContext(); while (true) { LookupQualifiedName(Previous, LookupDC); @@ -17572,16 +17648,12 @@ bool Sema::DefineUsedVTables() { // no key function or the key function is inlined. Don't warn in C++ ABIs // that lack key functions, since the user won't be able to make one. if (Context.getTargetInfo().getCXXABI().hasKeyFunctions() && - Class->isExternallyVisible() && ClassTSK != TSK_ImplicitInstantiation) { + Class->isExternallyVisible() && ClassTSK != TSK_ImplicitInstantiation && + ClassTSK != TSK_ExplicitInstantiationDefinition) { const FunctionDecl *KeyFunctionDef = nullptr; if (!KeyFunction || (KeyFunction->hasBody(KeyFunctionDef) && - KeyFunctionDef->isInlined())) { - Diag(Class->getLocation(), - ClassTSK == TSK_ExplicitInstantiationDefinition - ? diag::warn_weak_template_vtable - : diag::warn_weak_vtable) - << Class; - } + KeyFunctionDef->isInlined())) + Diag(Class->getLocation(), diag::warn_weak_vtable) << Class; } } VTableUses.clear(); |
