diff options
Diffstat (limited to 'clang/lib/Sema/SemaDeclCXX.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 1221 |
1 files changed, 815 insertions, 406 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 9916d3be77e1..22bf35dbd0cb 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -38,8 +38,9 @@ #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" -#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" #include <map> #include <set> @@ -51,102 +52,109 @@ using namespace clang; //===----------------------------------------------------------------------===// namespace { - /// CheckDefaultArgumentVisitor - C++ [dcl.fct.default] Traverses - /// the default argument of a parameter to determine whether it - /// contains any ill-formed subexpressions. For example, this will - /// diagnose the use of local variables or parameters within the - /// default argument expression. - class CheckDefaultArgumentVisitor - : public StmtVisitor<CheckDefaultArgumentVisitor, bool> { - Expr *DefaultArg; - Sema *S; +/// CheckDefaultArgumentVisitor - C++ [dcl.fct.default] Traverses +/// the default argument of a parameter to determine whether it +/// contains any ill-formed subexpressions. For example, this will +/// diagnose the use of local variables or parameters within the +/// default argument expression. +class CheckDefaultArgumentVisitor + : public ConstStmtVisitor<CheckDefaultArgumentVisitor, bool> { + Sema &S; + const Expr *DefaultArg; - public: - CheckDefaultArgumentVisitor(Expr *defarg, Sema *s) - : DefaultArg(defarg), S(s) {} - - bool VisitExpr(Expr *Node); - bool VisitDeclRefExpr(DeclRefExpr *DRE); - bool VisitCXXThisExpr(CXXThisExpr *ThisE); - bool VisitLambdaExpr(LambdaExpr *Lambda); - bool VisitPseudoObjectExpr(PseudoObjectExpr *POE); - }; +public: + CheckDefaultArgumentVisitor(Sema &S, const Expr *DefaultArg) + : S(S), DefaultArg(DefaultArg) {} + + bool VisitExpr(const Expr *Node); + bool VisitDeclRefExpr(const DeclRefExpr *DRE); + bool VisitCXXThisExpr(const CXXThisExpr *ThisE); + bool VisitLambdaExpr(const LambdaExpr *Lambda); + bool VisitPseudoObjectExpr(const PseudoObjectExpr *POE); +}; - /// VisitExpr - Visit all of the children of this expression. - bool CheckDefaultArgumentVisitor::VisitExpr(Expr *Node) { - bool IsInvalid = false; - for (Stmt *SubStmt : Node->children()) - IsInvalid |= Visit(SubStmt); - return IsInvalid; - } - - /// VisitDeclRefExpr - Visit a reference to a declaration, to - /// determine whether this declaration can be used in the default - /// argument expression. - bool CheckDefaultArgumentVisitor::VisitDeclRefExpr(DeclRefExpr *DRE) { - NamedDecl *Decl = DRE->getDecl(); - if (ParmVarDecl *Param = dyn_cast<ParmVarDecl>(Decl)) { - // C++ [dcl.fct.default]p9 - // Default arguments are evaluated each time the function is - // called. The order of evaluation of function arguments is - // unspecified. Consequently, parameters of a function shall not - // be used in default argument expressions, even if they are not - // evaluated. Parameters of a function declared before a default - // argument expression are in scope and can hide namespace and - // class member names. - return S->Diag(DRE->getBeginLoc(), - diag::err_param_default_argument_references_param) +/// VisitExpr - Visit all of the children of this expression. +bool CheckDefaultArgumentVisitor::VisitExpr(const Expr *Node) { + bool IsInvalid = false; + for (const Stmt *SubStmt : Node->children()) + IsInvalid |= Visit(SubStmt); + return IsInvalid; +} + +/// VisitDeclRefExpr - Visit a reference to a declaration, to +/// determine whether this declaration can be used in the default +/// argument expression. +bool CheckDefaultArgumentVisitor::VisitDeclRefExpr(const DeclRefExpr *DRE) { + const NamedDecl *Decl = DRE->getDecl(); + if (const auto *Param = dyn_cast<ParmVarDecl>(Decl)) { + // C++ [dcl.fct.default]p9: + // [...] parameters of a function shall not be used in default + // argument expressions, even if they are not evaluated. [...] + // + // C++17 [dcl.fct.default]p9 (by CWG 2082): + // [...] A parameter shall not appear as a potentially-evaluated + // expression in a default argument. [...] + // + if (DRE->isNonOdrUse() != NOUR_Unevaluated) + return S.Diag(DRE->getBeginLoc(), + diag::err_param_default_argument_references_param) << Param->getDeclName() << DefaultArg->getSourceRange(); - } else if (VarDecl *VDecl = dyn_cast<VarDecl>(Decl)) { - // C++ [dcl.fct.default]p7 - // Local variables shall not be used in default argument - // expressions. - if (VDecl->isLocalVarDecl()) - return S->Diag(DRE->getBeginLoc(), - diag::err_param_default_argument_references_local) - << VDecl->getDeclName() << DefaultArg->getSourceRange(); - } - - return false; - } - - /// VisitCXXThisExpr - Visit a C++ "this" expression. - bool CheckDefaultArgumentVisitor::VisitCXXThisExpr(CXXThisExpr *ThisE) { - // C++ [dcl.fct.default]p8: - // The keyword this shall not be used in a default argument of a - // member function. - return S->Diag(ThisE->getBeginLoc(), - diag::err_param_default_argument_references_this) - << ThisE->getSourceRange(); + } else if (const auto *VDecl = dyn_cast<VarDecl>(Decl)) { + // C++ [dcl.fct.default]p7: + // Local variables shall not be used in default argument + // expressions. + // + // C++17 [dcl.fct.default]p7 (by CWG 2082): + // A local variable shall not appear as a potentially-evaluated + // expression in a default argument. + // + // C++20 [dcl.fct.default]p7 (DR as part of P0588R1, see also CWG 2346): + // Note: A local variable cannot be odr-used (6.3) in a default argument. + // + if (VDecl->isLocalVarDecl() && !DRE->isNonOdrUse()) + return S.Diag(DRE->getBeginLoc(), + diag::err_param_default_argument_references_local) + << VDecl->getDeclName() << DefaultArg->getSourceRange(); } - bool CheckDefaultArgumentVisitor::VisitPseudoObjectExpr(PseudoObjectExpr *POE) { - bool Invalid = false; - for (PseudoObjectExpr::semantics_iterator - i = POE->semantics_begin(), e = POE->semantics_end(); i != e; ++i) { - Expr *E = *i; + return false; +} - // Look through bindings. - if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E)) { - E = OVE->getSourceExpr(); - assert(E && "pseudo-object binding without source expression?"); - } +/// VisitCXXThisExpr - Visit a C++ "this" expression. +bool CheckDefaultArgumentVisitor::VisitCXXThisExpr(const CXXThisExpr *ThisE) { + // C++ [dcl.fct.default]p8: + // The keyword this shall not be used in a default argument of a + // member function. + return S.Diag(ThisE->getBeginLoc(), + diag::err_param_default_argument_references_this) + << ThisE->getSourceRange(); +} - Invalid |= Visit(E); +bool CheckDefaultArgumentVisitor::VisitPseudoObjectExpr( + const PseudoObjectExpr *POE) { + bool Invalid = false; + for (const Expr *E : POE->semantics()) { + // Look through bindings. + if (const auto *OVE = dyn_cast<OpaqueValueExpr>(E)) { + E = OVE->getSourceExpr(); + assert(E && "pseudo-object binding without source expression?"); } - return Invalid; + + Invalid |= Visit(E); } + return Invalid; +} - bool CheckDefaultArgumentVisitor::VisitLambdaExpr(LambdaExpr *Lambda) { - // C++11 [expr.lambda.prim]p13: - // A lambda-expression appearing in a default argument shall not - // implicitly or explicitly capture any entity. - if (Lambda->capture_begin() == Lambda->capture_end()) - return false; +bool CheckDefaultArgumentVisitor::VisitLambdaExpr(const LambdaExpr *Lambda) { + // C++11 [expr.lambda.prim]p13: + // A lambda-expression appearing in a default argument shall not + // implicitly or explicitly capture any entity. + if (Lambda->capture_begin() == Lambda->capture_end()) + return false; - return S->Diag(Lambda->getBeginLoc(), diag::err_lambda_capture_default_arg); - } + return S.Diag(Lambda->getBeginLoc(), diag::err_lambda_capture_default_arg); } +} // namespace void Sema::ImplicitExceptionSpecification::CalledDecl(SourceLocation CallLoc, @@ -246,14 +254,12 @@ void Sema::ImplicitExceptionSpecification::CalledStmt(Stmt *S) { ComputedEST = EST_None; } -bool -Sema::SetParamDefaultArgument(ParmVarDecl *Param, Expr *Arg, - SourceLocation EqualLoc) { +ExprResult Sema::ConvertParamDefaultArgument(const ParmVarDecl *Param, + Expr *Arg, + SourceLocation EqualLoc) { if (RequireCompleteType(Param->getLocation(), Param->getType(), - diag::err_typecheck_decl_incomplete_type)) { - Param->setInvalidDecl(); + diag::err_typecheck_decl_incomplete_type)) return true; - } // C++ [dcl.fct.default]p5 // A default argument expression is implicitly converted (clause @@ -274,7 +280,12 @@ Sema::SetParamDefaultArgument(ParmVarDecl *Param, Expr *Arg, CheckCompletedExpr(Arg, EqualLoc); Arg = MaybeCreateExprWithCleanups(Arg); - // Okay: add the default argument to the parameter + return Arg; +} + +void Sema::SetParamDefaultArgument(ParmVarDecl *Param, Expr *Arg, + SourceLocation EqualLoc) { + // Add the default argument to the parameter Param->setDefaultArg(Arg); // We have already instantiated this parameter; provide each of the @@ -288,8 +299,6 @@ Sema::SetParamDefaultArgument(ParmVarDecl *Param, Expr *Arg, // We're done tracking this parameter's instantiations. UnparsedDefaultArgInstantiations.erase(InstPos); } - - return false; } /// ActOnParamDefaultArgument - Check whether the default argument @@ -304,18 +313,22 @@ Sema::ActOnParamDefaultArgument(Decl *param, SourceLocation EqualLoc, ParmVarDecl *Param = cast<ParmVarDecl>(param); UnparsedDefaultArgLocs.erase(Param); + auto Fail = [&] { + Param->setInvalidDecl(); + Param->setDefaultArg(new (Context) OpaqueValueExpr( + EqualLoc, Param->getType().getNonReferenceType(), VK_RValue)); + }; + // Default arguments are only permitted in C++ if (!getLangOpts().CPlusPlus) { Diag(EqualLoc, diag::err_param_default_argument) << DefaultArg->getSourceRange(); - Param->setInvalidDecl(); - return; + return Fail(); } // Check for unexpanded parameter packs. if (DiagnoseUnexpandedParameterPack(DefaultArg, UPPC_DefaultArgument)) { - Param->setInvalidDecl(); - return; + return Fail(); } // C++11 [dcl.fct.default]p3 @@ -324,15 +337,21 @@ Sema::ActOnParamDefaultArgument(Decl *param, SourceLocation EqualLoc, if (Param->isParameterPack()) { Diag(EqualLoc, diag::err_param_default_argument_on_parameter_pack) << DefaultArg->getSourceRange(); + // Recover by discarding the default argument. + Param->setDefaultArg(nullptr); return; } + ExprResult Result = ConvertParamDefaultArgument(Param, DefaultArg, EqualLoc); + if (Result.isInvalid()) + return Fail(); + + DefaultArg = Result.getAs<Expr>(); + // Check that the default argument is well-formed - CheckDefaultArgumentVisitor DefaultArgChecker(DefaultArg, this); - if (DefaultArgChecker.Visit(DefaultArg)) { - Param->setInvalidDecl(); - return; - } + CheckDefaultArgumentVisitor DefaultArgChecker(*this, DefaultArg); + if (DefaultArgChecker.Visit(DefaultArg)) + return Fail(); SetParamDefaultArgument(Param, DefaultArg, EqualLoc); } @@ -419,14 +438,9 @@ void Sema::CheckExtraCXXDefaultArguments(Declarator &D) { } static bool functionDeclHasDefaultArgument(const FunctionDecl *FD) { - for (unsigned NumParams = FD->getNumParams(); NumParams > 0; --NumParams) { - const ParmVarDecl *PVD = FD->getParamDecl(NumParams-1); - if (!PVD->hasDefaultArg()) - return false; - if (!PVD->hasInheritedDefaultArg()) - return true; - } - return false; + return std::any_of(FD->param_begin(), FD->param_end(), [](ParmVarDecl *P) { + return P->hasDefaultArg() && !P->hasInheritedDefaultArg(); + }); } /// MergeCXXFunctionDecl - Merge two declarations of the same C++ @@ -664,7 +678,7 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, // for the same class template shall not have equivalent // parameter-declaration-clauses. if (isa<CXXDeductionGuideDecl>(New) && - !New->isFunctionTemplateSpecialization()) { + !New->isFunctionTemplateSpecialization() && isVisible(Old)) { Diag(New->getLocation(), diag::err_deduction_guide_redeclared); Diag(Old->getLocation(), diag::note_previous_declaration); } @@ -761,7 +775,7 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D, Err << SourceRange(Loc, Loc); } else if (!CPlusPlus20Specifiers.empty()) { auto &&Warn = Diag(CPlusPlus20SpecifierLocs.front(), - getLangOpts().CPlusPlus2a + getLangOpts().CPlusPlus20 ? diag::warn_cxx17_compat_decomp_decl_spec : diag::ext_decomp_decl_spec); Warn << (int)CPlusPlus20Specifiers.size() @@ -778,7 +792,7 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D, // C++2a [dcl.struct.bind]p1: // A cv that includes volatile is deprecated if ((DS.getTypeQualifiers() & DeclSpec::TQ_volatile) && - getLangOpts().CPlusPlus2a) + getLangOpts().CPlusPlus20) Diag(DS.getVolatileSpecLoc(), diag::warn_deprecated_volatile_structured_binding); @@ -952,7 +966,7 @@ static std::string printTemplateArgs(const PrintingPolicy &PrintingPolicy, Arg.getArgument().print(PrintingPolicy, OS); First = false; } - return OS.str(); + return std::string(OS.str()); } static bool lookupStdTypeTraitMember(Sema &S, LookupResult &TraitMemberLookup, @@ -1052,7 +1066,7 @@ static IsTupleLike isTupleLike(Sema &S, SourceLocation Loc, QualType T, TemplateArgumentListInfo &Args; ICEDiagnoser(LookupResult &R, TemplateArgumentListInfo &Args) : R(R), Args(Args) {} - void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) { + void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) override { S.Diag(Loc, diag::err_decomp_decl_std_tuple_size_not_constant) << printTemplateArgs(S.Context.getPrintingPolicy(), Args); } @@ -1100,16 +1114,17 @@ static QualType getTupleLikeElementType(Sema &S, SourceLocation Loc, } namespace { -struct BindingDiagnosticTrap { +struct InitializingBinding { Sema &S; - DiagnosticErrorTrap Trap; - BindingDecl *BD; - - BindingDiagnosticTrap(Sema &S, BindingDecl *BD) - : S(S), Trap(S.Diags), BD(BD) {} - ~BindingDiagnosticTrap() { - if (Trap.hasErrorOccurred()) - S.Diag(BD->getLocation(), diag::note_in_binding_decl_init) << BD; + InitializingBinding(Sema &S, BindingDecl *BD) : S(S) { + Sema::CodeSynthesisContext Ctx; + Ctx.Kind = Sema::CodeSynthesisContext::InitializingStructuredBinding; + Ctx.PointOfInstantiation = BD->getLocation(); + Ctx.Entity = BD; + S.pushCodeSynthesisContext(Ctx); + } + ~InitializingBinding() { + S.popCodeSynthesisContext(); } }; } @@ -1158,7 +1173,7 @@ static bool checkTupleLikeDecomposition(Sema &S, unsigned I = 0; for (auto *B : Bindings) { - BindingDiagnosticTrap Trap(S, B); + InitializingBinding InitContext(S, B); SourceLocation Loc = B->getLocation(); ExprResult E = S.BuildDeclRefExpr(Src, DecompType, VK_LValue, Loc); @@ -1528,25 +1543,34 @@ void Sema::MergeVarDeclExceptionSpecs(VarDecl *New, VarDecl *Old) { /// [dcl.fct.default]. void Sema::CheckCXXDefaultArguments(FunctionDecl *FD) { unsigned NumParams = FD->getNumParams(); - unsigned p; + unsigned ParamIdx = 0; + + // This checking doesn't make sense for explicit specializations; their + // default arguments are determined by the declaration we're specializing, + // not by FD. + if (FD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) + return; + if (auto *FTD = FD->getDescribedFunctionTemplate()) + if (FTD->isMemberSpecialization()) + return; // Find first parameter with a default argument - for (p = 0; p < NumParams; ++p) { - ParmVarDecl *Param = FD->getParamDecl(p); + for (; ParamIdx < NumParams; ++ParamIdx) { + ParmVarDecl *Param = FD->getParamDecl(ParamIdx); if (Param->hasDefaultArg()) break; } - // C++11 [dcl.fct.default]p4: + // C++20 [dcl.fct.default]p4: // In a given function declaration, each parameter subsequent to a parameter // with a default argument shall have a default argument supplied in this or - // a previous declaration or shall be a function parameter pack. A default - // argument shall not be redefined by a later declaration (not even to the - // same value). - unsigned LastMissingDefaultArg = 0; - for (; p < NumParams; ++p) { - ParmVarDecl *Param = FD->getParamDecl(p); - if (!Param->hasDefaultArg() && !Param->isParameterPack()) { + // a previous declaration, unless the parameter was expanded from a + // parameter pack, or shall be a function parameter pack. + for (; ParamIdx < NumParams; ++ParamIdx) { + ParmVarDecl *Param = FD->getParamDecl(ParamIdx); + if (!Param->hasDefaultArg() && !Param->isParameterPack() && + !(CurrentInstantiationScope && + CurrentInstantiationScope->isLocalPackExpansion(Param))) { if (Param->isInvalidDecl()) /* We already complained about this parameter. */; else if (Param->getIdentifier()) @@ -1556,21 +1580,6 @@ void Sema::CheckCXXDefaultArguments(FunctionDecl *FD) { else Diag(Param->getLocation(), diag::err_param_default_argument_missing); - - LastMissingDefaultArg = p; - } - } - - if (LastMissingDefaultArg > 0) { - // Some default arguments were missing. Clear out all of the - // default arguments up to (and including) the last missing - // default argument, so that we leave the function parameters - // in a semantically valid state. - for (p = 0; p <= LastMissingDefaultArg; ++p) { - ParmVarDecl *Param = FD->getParamDecl(p); - if (Param->hasDefaultArg()) { - Param->setDefaultArg(nullptr); - } } } } @@ -1716,7 +1725,7 @@ bool Sema::CheckConstexprFunctionDefinition(const FunctionDecl *NewFD, // - it shall not be virtual; (removed in C++20) const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(NewFD); if (Method && Method->isVirtual()) { - if (getLangOpts().CPlusPlus2a) { + if (getLangOpts().CPlusPlus20) { if (Kind == CheckConstexprKind::Diagnose) Diag(Method->getLocation(), diag::warn_cxx17_compat_constexpr_virtual); } else { @@ -1856,11 +1865,11 @@ static bool CheckConstexprDeclStmt(Sema &SemaRef, const FunctionDecl *Dcl, if (Kind == Sema::CheckConstexprKind::Diagnose) { SemaRef.Diag( VD->getLocation(), - SemaRef.getLangOpts().CPlusPlus2a + SemaRef.getLangOpts().CPlusPlus20 ? diag::warn_cxx17_compat_constexpr_local_var_no_init : diag::ext_constexpr_local_var_no_init) << isa<CXXConstructorDecl>(Dcl); - } else if (!SemaRef.getLangOpts().CPlusPlus2a) { + } else if (!SemaRef.getLangOpts().CPlusPlus20) { return false; } continue; @@ -1919,7 +1928,7 @@ static bool CheckConstexprCtorInitializer(Sema &SemaRef, Sema::CheckConstexprKind Kind) { // In C++20 onwards, there's nothing to check for validity. if (Kind == Sema::CheckConstexprKind::CheckValid && - SemaRef.getLangOpts().CPlusPlus2a) + SemaRef.getLangOpts().CPlusPlus20) return true; if (Field->isInvalidDecl()) @@ -1941,14 +1950,14 @@ static bool CheckConstexprCtorInitializer(Sema &SemaRef, if (Kind == Sema::CheckConstexprKind::Diagnose) { if (!Diagnosed) { SemaRef.Diag(Dcl->getLocation(), - SemaRef.getLangOpts().CPlusPlus2a + SemaRef.getLangOpts().CPlusPlus20 ? diag::warn_cxx17_compat_constexpr_ctor_missing_init : diag::ext_constexpr_ctor_missing_init); Diagnosed = true; } SemaRef.Diag(Field->getLocation(), diag::note_constexpr_ctor_missing_init); - } else if (!SemaRef.getLangOpts().CPlusPlus2a) { + } else if (!SemaRef.getLangOpts().CPlusPlus20) { return false; } } else if (Field->isAnonymousStructOrUnion()) { @@ -2132,14 +2141,14 @@ static bool CheckConstexprFunctionBody(Sema &SemaRef, const FunctionDecl *Dcl, // apply the general constexpr rules. switch (Kind) { case Sema::CheckConstexprKind::CheckValid: - if (!SemaRef.getLangOpts().CPlusPlus2a) + if (!SemaRef.getLangOpts().CPlusPlus20) return false; break; case Sema::CheckConstexprKind::Diagnose: SemaRef.Diag(Body->getBeginLoc(), - !SemaRef.getLangOpts().CPlusPlus2a - ? diag::ext_constexpr_function_try_block_cxx2a + !SemaRef.getLangOpts().CPlusPlus20 + ? diag::ext_constexpr_function_try_block_cxx20 : diag::warn_cxx17_compat_constexpr_function_try_block) << isa<CXXConstructorDecl>(Dcl); break; @@ -2162,14 +2171,14 @@ static bool CheckConstexprFunctionBody(Sema &SemaRef, const FunctionDecl *Dcl, if (Kind == Sema::CheckConstexprKind::CheckValid) { // If this is only valid as an extension, report that we don't satisfy the // constraints of the current language. - if ((Cxx2aLoc.isValid() && !SemaRef.getLangOpts().CPlusPlus2a) || + if ((Cxx2aLoc.isValid() && !SemaRef.getLangOpts().CPlusPlus20) || (Cxx1yLoc.isValid() && !SemaRef.getLangOpts().CPlusPlus17)) return false; } else if (Cxx2aLoc.isValid()) { SemaRef.Diag(Cxx2aLoc, - SemaRef.getLangOpts().CPlusPlus2a + SemaRef.getLangOpts().CPlusPlus20 ? diag::warn_cxx17_compat_constexpr_body_invalid_stmt - : diag::ext_constexpr_body_invalid_stmt_cxx2a) + : diag::ext_constexpr_body_invalid_stmt_cxx20) << isa<CXXConstructorDecl>(Dcl); } else if (Cxx1yLoc.isValid()) { SemaRef.Diag(Cxx1yLoc, @@ -2194,10 +2203,10 @@ static bool CheckConstexprFunctionBody(Sema &SemaRef, const FunctionDecl *Dcl, if (Kind == Sema::CheckConstexprKind::Diagnose) { SemaRef.Diag( Dcl->getLocation(), - SemaRef.getLangOpts().CPlusPlus2a + SemaRef.getLangOpts().CPlusPlus20 ? diag::warn_cxx17_compat_constexpr_union_ctor_no_init : diag::ext_constexpr_union_ctor_no_init); - } else if (!SemaRef.getLangOpts().CPlusPlus2a) { + } else if (!SemaRef.getLangOpts().CPlusPlus20) { return false; } } @@ -2306,7 +2315,7 @@ static bool CheckConstexprFunctionBody(Sema &SemaRef, const FunctionDecl *Dcl, !Expr::isPotentialConstantExpr(Dcl, Diags)) { SemaRef.Diag(Dcl->getLocation(), diag::ext_constexpr_function_never_constant_expr) - << isa<CXXConstructorDecl>(Dcl); + << isa<CXXConstructorDecl>(Dcl) << Dcl->isConsteval(); for (size_t I = 0, N = Diags.size(); I != N; ++I) SemaRef.Diag(Diags[I].first, Diags[I].second); // Don't return false here: we allow this for compatibility in @@ -2417,7 +2426,10 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, TypeSourceInfo *TInfo, SourceLocation EllipsisLoc) { QualType BaseType = TInfo->getType(); - + if (BaseType->containsErrors()) { + // Already emitted a diagnostic when parsing the error type. + return nullptr; + } // C++ [class.union]p1: // A union shall not have base classes. if (Class->isUnion()) { @@ -2821,13 +2833,13 @@ void Sema::BuildBasePathArray(const CXXBasePaths &Paths, /// if there is an error, and Range is the source range to highlight /// if there is an error. /// -/// If either InaccessibleBaseID or AmbigiousBaseConvID are 0, then the +/// If either InaccessibleBaseID or AmbiguousBaseConvID are 0, then the /// diagnostic for the respective type of error will be suppressed, but the /// check for ill-formed code will still be performed. bool Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, unsigned InaccessibleBaseID, - unsigned AmbigiousBaseConvID, + unsigned AmbiguousBaseConvID, SourceLocation Loc, SourceRange Range, DeclarationName Name, CXXCastPath *BasePath, @@ -2853,7 +2865,7 @@ Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, for (const CXXBasePath &PossiblePath : Paths) { if (PossiblePath.size() == 1) { Path = &PossiblePath; - if (AmbigiousBaseConvID) + if (AmbiguousBaseConvID) Diag(Loc, diag::ext_ms_ambiguous_direct_base) << Base << Derived << Range; break; @@ -2881,7 +2893,7 @@ Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, return false; } - if (AmbigiousBaseConvID) { + if (AmbiguousBaseConvID) { // We know that the derived-to-base conversion is ambiguous, and // we're going to produce a diagnostic. Perform the derived-to-base // search just one more time to compute all of the possible paths so @@ -2900,7 +2912,7 @@ Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, // to each base class subobject. std::string PathDisplayStr = getAmbiguousPathsDisplayString(Paths); - Diag(Loc, AmbigiousBaseConvID) + Diag(Loc, AmbiguousBaseConvID) << Derived << Base << PathDisplayStr << Range << Name; } return true; @@ -3033,7 +3045,7 @@ void Sema::CheckOverrideControl(NamedDecl *D) { << MD->getDeclName(); } -void Sema::DiagnoseAbsenceOfOverrideControl(NamedDecl *D) { +void Sema::DiagnoseAbsenceOfOverrideControl(NamedDecl *D, bool Inconsistent) { if (D->isInvalidDecl() || D->hasAttr<OverrideAttr>()) return; CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D); @@ -3049,12 +3061,22 @@ void Sema::DiagnoseAbsenceOfOverrideControl(NamedDecl *D) { return; if (MD->size_overridden_methods() > 0) { - unsigned DiagID = isa<CXXDestructorDecl>(MD) - ? diag::warn_destructor_marked_not_override_overriding - : diag::warn_function_marked_not_override_overriding; - Diag(MD->getLocation(), DiagID) << MD->getDeclName(); - const CXXMethodDecl *OMD = *MD->begin_overridden_methods(); - Diag(OMD->getLocation(), diag::note_overridden_virtual_function); + auto EmitDiag = [&](unsigned DiagInconsistent, unsigned DiagSuggest) { + unsigned DiagID = + Inconsistent && !Diags.isIgnored(DiagInconsistent, MD->getLocation()) + ? DiagInconsistent + : DiagSuggest; + Diag(MD->getLocation(), DiagID) << MD->getDeclName(); + const CXXMethodDecl *OMD = *MD->begin_overridden_methods(); + Diag(OMD->getLocation(), diag::note_overridden_virtual_function); + }; + if (isa<CXXDestructorDecl>(MD)) + EmitDiag( + diag::warn_inconsistent_destructor_marked_not_override_overriding, + diag::warn_suggest_destructor_marked_not_override_overriding); + else + EmitDiag(diag::warn_inconsistent_function_marked_not_override_overriding, + diag::warn_suggest_function_marked_not_override_overriding); } } @@ -5443,6 +5465,15 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location, // subobjects. bool VisitVirtualBases = !ClassDecl->isAbstract(); + // If the destructor exists and has already been marked used in the MS ABI, + // then virtual base destructors have already been checked and marked used. + // Skip checking them again to avoid duplicate diagnostics. + if (Context.getTargetInfo().getCXXABI().isMicrosoft()) { + CXXDestructorDecl *Dtor = ClassDecl->getDestructor(); + if (Dtor && Dtor->isUsed()) + VisitVirtualBases = false; + } + llvm::SmallPtrSet<const RecordType *, 8> DirectVirtualBases; // Bases. @@ -5477,16 +5508,21 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location, DiagnoseUseOfDecl(Dtor, Location); } - if (!VisitVirtualBases) - return; + if (VisitVirtualBases) + MarkVirtualBaseDestructorsReferenced(Location, ClassDecl, + &DirectVirtualBases); +} +void Sema::MarkVirtualBaseDestructorsReferenced( + SourceLocation Location, CXXRecordDecl *ClassDecl, + llvm::SmallPtrSetImpl<const RecordType *> *DirectVirtualBases) { // Virtual bases. for (const auto &VBase : ClassDecl->vbases()) { // Bases are always records in a well-formed non-dependent class. const RecordType *RT = VBase.getType()->castAs<RecordType>(); - // Ignore direct virtual bases. - if (DirectVirtualBases.count(RT)) + // Ignore already visited direct virtual bases. + if (DirectVirtualBases && DirectVirtualBases->count(RT)) continue; CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(RT->getDecl()); @@ -5788,6 +5824,23 @@ static void ReferenceDllExportedMembers(Sema &S, CXXRecordDecl *Class) { // declaration. return; + // Add a context note to explain how we got to any diagnostics produced below. + struct MarkingClassDllexported { + Sema &S; + MarkingClassDllexported(Sema &S, CXXRecordDecl *Class, + SourceLocation AttrLoc) + : S(S) { + Sema::CodeSynthesisContext Ctx; + Ctx.Kind = Sema::CodeSynthesisContext::MarkingClassDllexported; + Ctx.PointOfInstantiation = AttrLoc; + Ctx.Entity = Class; + S.pushCodeSynthesisContext(Ctx); + } + ~MarkingClassDllexported() { + S.popCodeSynthesisContext(); + } + } MarkingDllexportedContext(S, Class, ClassAttr->getLocation()); + if (S.Context.getTargetInfo().getTriple().isWindowsGNUEnvironment()) S.MarkVTableUsed(Class->getLocation(), Class, true); @@ -5823,13 +5876,7 @@ static void ReferenceDllExportedMembers(Sema &S, CXXRecordDecl *Class) { // defaulted 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. - DiagnosticErrorTrap Trap(S.Diags); S.MarkFunctionReferenced(Class->getLocation(), MD); - if (Trap.hasErrorOccurred()) { - S.Diag(ClassAttr->getLocation(), diag::note_due_to_dllexported_class) - << Class << !S.getLangOpts().CPlusPlus11; - break; - } // There is no later point when we will see the definition of this // function, so pass it to the consumer now. @@ -5877,6 +5924,123 @@ static void checkForMultipleExportedDefaultConstructors(Sema &S, } } +static void checkCUDADeviceBuiltinSurfaceClassTemplate(Sema &S, + CXXRecordDecl *Class) { + bool ErrorReported = false; + auto reportIllegalClassTemplate = [&ErrorReported](Sema &S, + ClassTemplateDecl *TD) { + if (ErrorReported) + return; + S.Diag(TD->getLocation(), + diag::err_cuda_device_builtin_surftex_cls_template) + << /*surface*/ 0 << TD; + ErrorReported = true; + }; + + ClassTemplateDecl *TD = Class->getDescribedClassTemplate(); + if (!TD) { + auto *SD = dyn_cast<ClassTemplateSpecializationDecl>(Class); + if (!SD) { + S.Diag(Class->getLocation(), + diag::err_cuda_device_builtin_surftex_ref_decl) + << /*surface*/ 0 << Class; + S.Diag(Class->getLocation(), + diag::note_cuda_device_builtin_surftex_should_be_template_class) + << Class; + return; + } + TD = SD->getSpecializedTemplate(); + } + + TemplateParameterList *Params = TD->getTemplateParameters(); + unsigned N = Params->size(); + + if (N != 2) { + reportIllegalClassTemplate(S, TD); + S.Diag(TD->getLocation(), + diag::note_cuda_device_builtin_surftex_cls_should_have_n_args) + << TD << 2; + } + if (N > 0 && !isa<TemplateTypeParmDecl>(Params->getParam(0))) { + reportIllegalClassTemplate(S, TD); + S.Diag(TD->getLocation(), + diag::note_cuda_device_builtin_surftex_cls_should_have_match_arg) + << TD << /*1st*/ 0 << /*type*/ 0; + } + if (N > 1) { + auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Params->getParam(1)); + if (!NTTP || !NTTP->getType()->isIntegralOrEnumerationType()) { + reportIllegalClassTemplate(S, TD); + S.Diag(TD->getLocation(), + diag::note_cuda_device_builtin_surftex_cls_should_have_match_arg) + << TD << /*2nd*/ 1 << /*integer*/ 1; + } + } +} + +static void checkCUDADeviceBuiltinTextureClassTemplate(Sema &S, + CXXRecordDecl *Class) { + bool ErrorReported = false; + auto reportIllegalClassTemplate = [&ErrorReported](Sema &S, + ClassTemplateDecl *TD) { + if (ErrorReported) + return; + S.Diag(TD->getLocation(), + diag::err_cuda_device_builtin_surftex_cls_template) + << /*texture*/ 1 << TD; + ErrorReported = true; + }; + + ClassTemplateDecl *TD = Class->getDescribedClassTemplate(); + if (!TD) { + auto *SD = dyn_cast<ClassTemplateSpecializationDecl>(Class); + if (!SD) { + S.Diag(Class->getLocation(), + diag::err_cuda_device_builtin_surftex_ref_decl) + << /*texture*/ 1 << Class; + S.Diag(Class->getLocation(), + diag::note_cuda_device_builtin_surftex_should_be_template_class) + << Class; + return; + } + TD = SD->getSpecializedTemplate(); + } + + TemplateParameterList *Params = TD->getTemplateParameters(); + unsigned N = Params->size(); + + if (N != 3) { + reportIllegalClassTemplate(S, TD); + S.Diag(TD->getLocation(), + diag::note_cuda_device_builtin_surftex_cls_should_have_n_args) + << TD << 3; + } + if (N > 0 && !isa<TemplateTypeParmDecl>(Params->getParam(0))) { + reportIllegalClassTemplate(S, TD); + S.Diag(TD->getLocation(), + diag::note_cuda_device_builtin_surftex_cls_should_have_match_arg) + << TD << /*1st*/ 0 << /*type*/ 0; + } + if (N > 1) { + auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Params->getParam(1)); + if (!NTTP || !NTTP->getType()->isIntegralOrEnumerationType()) { + reportIllegalClassTemplate(S, TD); + S.Diag(TD->getLocation(), + diag::note_cuda_device_builtin_surftex_cls_should_have_match_arg) + << TD << /*2nd*/ 1 << /*integer*/ 1; + } + } + if (N > 2) { + auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Params->getParam(2)); + if (!NTTP || !NTTP->getType()->isIntegralOrEnumerationType()) { + reportIllegalClassTemplate(S, TD); + S.Diag(TD->getLocation(), + diag::note_cuda_device_builtin_surftex_cls_should_have_match_arg) + << TD << /*3rd*/ 2 << /*integer*/ 1; + } + } +} + void Sema::checkClassLevelCodeSegAttribute(CXXRecordDecl *Class) { // Mark any compiler-generated routines with the implicit code_seg attribute. for (auto *Method : Class->methods()) { @@ -6151,7 +6315,7 @@ Sema::getDefaultedFunctionKind(const FunctionDecl *FD) { case OO_Spaceship: // No point allowing this if <=> doesn't exist in the current language mode. - if (!getLangOpts().CPlusPlus2a) + if (!getLangOpts().CPlusPlus20) break; return DefaultedComparisonKind::ThreeWay; @@ -6160,7 +6324,7 @@ Sema::getDefaultedFunctionKind(const FunctionDecl *FD) { case OO_Greater: case OO_GreaterEqual: // No point allowing this if <=> doesn't exist in the current language mode. - if (!getLangOpts().CPlusPlus2a) + if (!getLangOpts().CPlusPlus20) break; return DefaultedComparisonKind::Relational; @@ -6172,27 +6336,31 @@ Sema::getDefaultedFunctionKind(const FunctionDecl *FD) { return DefaultedFunctionKind(); } -static void DefineImplicitSpecialMember(Sema &S, CXXMethodDecl *MD, - SourceLocation DefaultLoc) { - switch (S.getSpecialMember(MD)) { +static void DefineDefaultedFunction(Sema &S, FunctionDecl *FD, + SourceLocation DefaultLoc) { + Sema::DefaultedFunctionKind DFK = S.getDefaultedFunctionKind(FD); + if (DFK.isComparison()) + return S.DefineDefaultedComparison(DefaultLoc, FD, DFK.asComparison()); + + switch (DFK.asSpecialMember()) { case Sema::CXXDefaultConstructor: S.DefineImplicitDefaultConstructor(DefaultLoc, - cast<CXXConstructorDecl>(MD)); + cast<CXXConstructorDecl>(FD)); break; case Sema::CXXCopyConstructor: - S.DefineImplicitCopyConstructor(DefaultLoc, cast<CXXConstructorDecl>(MD)); + S.DefineImplicitCopyConstructor(DefaultLoc, cast<CXXConstructorDecl>(FD)); break; case Sema::CXXCopyAssignment: - S.DefineImplicitCopyAssignment(DefaultLoc, MD); + S.DefineImplicitCopyAssignment(DefaultLoc, cast<CXXMethodDecl>(FD)); break; case Sema::CXXDestructor: - S.DefineImplicitDestructor(DefaultLoc, cast<CXXDestructorDecl>(MD)); + S.DefineImplicitDestructor(DefaultLoc, cast<CXXDestructorDecl>(FD)); break; case Sema::CXXMoveConstructor: - S.DefineImplicitMoveConstructor(DefaultLoc, cast<CXXConstructorDecl>(MD)); + S.DefineImplicitMoveConstructor(DefaultLoc, cast<CXXConstructorDecl>(FD)); break; case Sema::CXXMoveAssignment: - S.DefineImplicitMoveAssignment(DefaultLoc, MD); + S.DefineImplicitMoveAssignment(DefaultLoc, cast<CXXMethodDecl>(FD)); break; case Sema::CXXInvalid: llvm_unreachable("Invalid special member."); @@ -6313,6 +6481,27 @@ static bool canPassInRegisters(Sema &S, CXXRecordDecl *D, return HasNonDeletedCopyOrMove; } +/// Report an error regarding overriding, along with any relevant +/// overridden methods. +/// +/// \param DiagID the primary error to report. +/// \param MD the overriding method. +static bool +ReportOverrides(Sema &S, unsigned DiagID, const CXXMethodDecl *MD, + llvm::function_ref<bool(const CXXMethodDecl *)> Report) { + bool IssuedDiagnostic = false; + for (const CXXMethodDecl *O : MD->overridden_methods()) { + if (Report(O)) { + if (!IssuedDiagnostic) { + S.Diag(MD->getLocation(), DiagID) << MD->getDeclName(); + IssuedDiagnostic = true; + } + S.Diag(O->getLocation(), diag::note_overridden_virtual_function); + } + } + return IssuedDiagnostic; +} + /// Perform semantic checks on a class definition that has been /// completing, introducing implicitly-declared members, checking for /// abstract types, etc. @@ -6427,21 +6616,64 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) { // primary comparison functions (==, <=>). llvm::SmallVector<FunctionDecl*, 5> DefaultedSecondaryComparisons; - auto CheckForDefaultedFunction = [&](FunctionDecl *FD) { - if (!FD || FD->isInvalidDecl() || !FD->isExplicitlyDefaulted()) + // Perform checks that can't be done until we know all the properties of a + // member function (whether it's defaulted, deleted, virtual, overriding, + // ...). + auto CheckCompletedMemberFunction = [&](CXXMethodDecl *MD) { + // A static function cannot override anything. + if (MD->getStorageClass() == SC_Static) { + if (ReportOverrides(*this, diag::err_static_overrides_virtual, MD, + [](const CXXMethodDecl *) { return true; })) + return; + } + + // A deleted function cannot override a non-deleted function and vice + // versa. + if (ReportOverrides(*this, + MD->isDeleted() ? diag::err_deleted_override + : diag::err_non_deleted_override, + MD, [&](const CXXMethodDecl *V) { + return MD->isDeleted() != V->isDeleted(); + })) { + if (MD->isDefaulted() && MD->isDeleted()) + // Explain why this defaulted function was deleted. + DiagnoseDeletedDefaultedFunction(MD); return; + } + + // A consteval function cannot override a non-consteval function and vice + // versa. + if (ReportOverrides(*this, + MD->isConsteval() ? diag::err_consteval_override + : diag::err_non_consteval_override, + MD, [&](const CXXMethodDecl *V) { + return MD->isConsteval() != V->isConsteval(); + })) { + if (MD->isDefaulted() && MD->isDeleted()) + // Explain why this defaulted function was deleted. + DiagnoseDeletedDefaultedFunction(MD); + return; + } + }; + + auto CheckForDefaultedFunction = [&](FunctionDecl *FD) -> bool { + if (!FD || FD->isInvalidDecl() || !FD->isExplicitlyDefaulted()) + return false; DefaultedFunctionKind DFK = getDefaultedFunctionKind(FD); if (DFK.asComparison() == DefaultedComparisonKind::NotEqual || - DFK.asComparison() == DefaultedComparisonKind::Relational) + DFK.asComparison() == DefaultedComparisonKind::Relational) { DefaultedSecondaryComparisons.push_back(FD); - else - CheckExplicitlyDefaultedFunction(S, FD); + return true; + } + + CheckExplicitlyDefaultedFunction(S, FD); + return false; }; auto CompleteMemberFunction = [&](CXXMethodDecl *M) { // Check whether the explicitly-defaulted members are valid. - CheckForDefaultedFunction(M); + bool Incomplete = CheckForDefaultedFunction(M); // Skip the rest of the checks for a member of a dependent class. if (Record->isDependentType()) @@ -6488,7 +6720,10 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) { // function right away. // FIXME: We can defer doing this until the vtable is marked as used. if (M->isDefaulted() && M->isConstexpr() && M->size_overridden_methods()) - DefineImplicitSpecialMember(*this, M, M->getLocation()); + DefineDefaultedFunction(*this, M, M->getLocation()); + + if (!Incomplete) + CheckCompletedMemberFunction(M); }; // Check the destructor before any other member function. We need to @@ -6524,19 +6759,21 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) { } } - if (HasMethodWithOverrideControl && - HasOverridingMethodWithoutOverrideControl) { - // At least one method has the 'override' control declared. - // Diagnose all other overridden methods which do not have 'override' - // specified on them. + if (HasOverridingMethodWithoutOverrideControl) { + bool HasInconsistentOverrideControl = HasMethodWithOverrideControl; for (auto *M : Record->methods()) - DiagnoseAbsenceOfOverrideControl(M); + DiagnoseAbsenceOfOverrideControl(M, HasInconsistentOverrideControl); } // Check the defaulted secondary comparisons after any other member functions. - for (FunctionDecl *FD : DefaultedSecondaryComparisons) + for (FunctionDecl *FD : DefaultedSecondaryComparisons) { CheckExplicitlyDefaultedFunction(S, FD); + // If this is a member function, we deferred checking it until now. + if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) + CheckCompletedMemberFunction(MD); + } + // ms_struct is a request to use the same ABI rules as MSVC. Check // whether this class uses any C++ features that are implemented // completely differently in MSVC, and if so, emit a diagnostic. @@ -6546,7 +6783,11 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) { // headers, sweeping up a bunch of types that the project doesn't // really rely on MSVC-compatible layout for. We must therefore // support "ms_struct except for C++ stuff" as a secondary ABI. - if (Record->isMsStruct(Context) && + // Don't emit this diagnostic if the feature was enabled as a + // language option (as opposed to via a pragma or attribute), as + // the option -mms-bitfields otherwise essentially makes it impossible + // to build C++ code, unless this diagnostic is turned off. + if (Record->isMsStruct(Context) && !Context.getLangOpts().MSBitfields && (Record->isPolymorphic() || Record->getNumBases())) { Diag(Record->getLocation(), diag::warn_cxx_ms_struct); } @@ -6581,6 +6822,13 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) { // is especially required for cases like vtable assumption loads. MarkVTableUsed(Record->getInnerLocStart(), Record); } + + if (getLangOpts().CUDA) { + if (Record->hasAttr<CUDADeviceBuiltinSurfaceTypeAttr>()) + checkCUDADeviceBuiltinSurfaceClassTemplate(*this, Record); + else if (Record->hasAttr<CUDADeviceBuiltinTextureTypeAttr>()) + checkCUDADeviceBuiltinTextureClassTemplate(*this, Record); + } } /// Look up the special member function that would be called by a special @@ -6955,7 +7203,7 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, // C++2a changes the second bullet to instead delete the function if it's // defaulted on its first declaration, unless it's "an assignment operator, // and its return type differs or its parameter type is not a reference". - bool DeleteOnTypeMismatch = getLangOpts().CPlusPlus2a && First; + bool DeleteOnTypeMismatch = getLangOpts().CPlusPlus20 && First; bool ShouldDeleteForTypeMismatch = false; unsigned ExpectedParams = 1; if (CSM == CXXDefaultConstructor || CSM == CXXDestructor) @@ -7065,7 +7313,7 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, // FIXME: This should not apply if the member is deleted. bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, RD, CSM, HasConstParam); - if ((getLangOpts().CPlusPlus2a || + if ((getLangOpts().CPlusPlus20 || (getLangOpts().CPlusPlus14 ? !isa<CXXDestructorDecl>(MD) : isa<CXXConstructorDecl>(MD))) && MD->isConstexpr() && !Constexpr && @@ -7083,7 +7331,9 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, // If a function is explicitly defaulted on its first declaration, it is // implicitly considered to be constexpr if the implicit declaration // would be. - MD->setConstexprKind(Constexpr ? CSK_constexpr : CSK_unspecified); + MD->setConstexprKind( + Constexpr ? (MD->isConsteval() ? CSK_consteval : CSK_constexpr) + : CSK_unspecified); if (!Type->hasExceptionSpec()) { // C++2a [except.spec]p3: @@ -7373,7 +7623,14 @@ private: /// resolution [...] CandidateSet.exclude(FD); - S.LookupOverloadedBinOp(CandidateSet, OO, Fns, Args); + if (Args[0]->getType()->isOverloadableType()) + S.LookupOverloadedBinOp(CandidateSet, OO, Fns, Args); + else { + // FIXME: We determine whether this is a valid expression by checking to + // see if there's a viable builtin operator candidate for it. That isn't + // really what the rules ask us to do, but should give the right results. + S.AddBuiltinOperatorCandidates(OO, FD->getLocation(), Args, CandidateSet); + } Result R; @@ -7438,6 +7695,31 @@ private: if (OO == OO_Spaceship && FD->getReturnType()->isUndeducedAutoType()) { if (auto *BestFD = Best->Function) { + // If any callee has an undeduced return type, deduce it now. + // FIXME: It's not clear how a failure here should be handled. For + // now, we produce an eager diagnostic, because that is forward + // compatible with most (all?) other reasonable options. + if (BestFD->getReturnType()->isUndeducedType() && + S.DeduceReturnType(BestFD, FD->getLocation(), + /*Diagnose=*/false)) { + // Don't produce a duplicate error when asked to explain why the + // comparison is deleted: we diagnosed that when initially checking + // the defaulted operator. + if (Diagnose == NoDiagnostics) { + S.Diag( + FD->getLocation(), + diag::err_defaulted_comparison_cannot_deduce_undeduced_auto) + << Subobj.Kind << Subobj.Decl; + S.Diag( + Subobj.Loc, + diag::note_defaulted_comparison_cannot_deduce_undeduced_auto) + << Subobj.Kind << Subobj.Decl; + S.Diag(BestFD->getLocation(), + diag::note_defaulted_comparison_cannot_deduce_callee) + << Subobj.Kind << Subobj.Decl; + } + return Result::deleted(); + } if (auto *Info = S.Context.CompCategories.lookupInfoForType( BestFD->getCallResultType())) { R.Category = Info->Kind; @@ -7826,10 +8108,14 @@ private: return StmtError(); OverloadedOperatorKind OO = FD->getOverloadedOperator(); - ExprResult Op = S.CreateOverloadedBinOp( - Loc, BinaryOperator::getOverloadedOpcode(OO), Fns, - Obj.first.get(), Obj.second.get(), /*PerformADL=*/true, - /*AllowRewrittenCandidates=*/true, FD); + BinaryOperatorKind Opc = BinaryOperator::getOverloadedOpcode(OO); + ExprResult Op; + if (Type->isOverloadableType()) + Op = S.CreateOverloadedBinOp(Loc, Opc, Fns, Obj.first.get(), + Obj.second.get(), /*PerformADL=*/true, + /*AllowRewrittenCandidates=*/true, FD); + else + Op = S.CreateBuiltinBinOp(Loc, Opc, Obj.first.get(), Obj.second.get()); if (Op.isInvalid()) return StmtError(); @@ -7869,8 +8155,12 @@ private: llvm::APInt ZeroVal(S.Context.getIntWidth(S.Context.IntTy), 0); Expr *Zero = IntegerLiteral::Create(S.Context, ZeroVal, S.Context.IntTy, Loc); - ExprResult Comp = S.CreateOverloadedBinOp(Loc, BO_NE, Fns, VDRef.get(), - Zero, true, true, FD); + ExprResult Comp; + if (VDRef.get()->getType()->isOverloadableType()) + Comp = S.CreateOverloadedBinOp(Loc, BO_NE, Fns, VDRef.get(), Zero, true, + true, FD); + else + Comp = S.CreateBuiltinBinOp(Loc, BO_NE, VDRef.get(), Zero); if (Comp.isInvalid()) return StmtError(); Sema::ConditionResult Cond = S.ActOnCondition( @@ -9423,27 +9713,57 @@ void Sema::DiagnoseHiddenVirtualMethods(CXXMethodDecl *MD) { } void Sema::checkIllFormedTrivialABIStruct(CXXRecordDecl &RD) { - auto PrintDiagAndRemoveAttr = [&]() { + auto PrintDiagAndRemoveAttr = [&](unsigned N) { // No diagnostics if this is a template instantiation. - if (!isTemplateInstantiation(RD.getTemplateSpecializationKind())) + if (!isTemplateInstantiation(RD.getTemplateSpecializationKind())) { Diag(RD.getAttr<TrivialABIAttr>()->getLocation(), diag::ext_cannot_use_trivial_abi) << &RD; + Diag(RD.getAttr<TrivialABIAttr>()->getLocation(), + diag::note_cannot_use_trivial_abi_reason) << &RD << N; + } RD.dropAttr<TrivialABIAttr>(); }; + // Ill-formed if the copy and move constructors are deleted. + auto HasNonDeletedCopyOrMoveConstructor = [&]() { + // If the type is dependent, then assume it might have + // implicit copy or move ctor because we won't know yet at this point. + if (RD.isDependentType()) + return true; + if (RD.needsImplicitCopyConstructor() && + !RD.defaultedCopyConstructorIsDeleted()) + return true; + if (RD.needsImplicitMoveConstructor() && + !RD.defaultedMoveConstructorIsDeleted()) + return true; + for (const CXXConstructorDecl *CD : RD.ctors()) + if (CD->isCopyOrMoveConstructor() && !CD->isDeleted()) + return true; + return false; + }; + + if (!HasNonDeletedCopyOrMoveConstructor()) { + PrintDiagAndRemoveAttr(0); + return; + } + // Ill-formed if the struct has virtual functions. if (RD.isPolymorphic()) { - PrintDiagAndRemoveAttr(); + PrintDiagAndRemoveAttr(1); 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(); + if (!B.getType()->isDependentType() && + !B.getType()->getAsCXXRecordDecl()->canPassInRegisters()) { + PrintDiagAndRemoveAttr(2); + return; + } + + if (B.isVirtual()) { + PrintDiagAndRemoveAttr(3); return; } } @@ -9453,14 +9773,14 @@ void Sema::checkIllFormedTrivialABIStruct(CXXRecordDecl &RD) { // non-trivial for the purpose of calls. QualType FT = FD->getType(); if (FT.getObjCLifetime() == Qualifiers::OCL_Weak) { - PrintDiagAndRemoveAttr(); + PrintDiagAndRemoveAttr(4); return; } if (const auto *RT = FT->getBaseElementTypeUnsafe()->getAs<RecordType>()) if (!RT->isDependentType() && !cast<CXXRecordDecl>(RT->getDecl())->canPassInRegisters()) { - PrintDiagAndRemoveAttr(); + PrintDiagAndRemoveAttr(5); return; } } @@ -9533,86 +9853,95 @@ static void findImplicitlyDeclaredEqualityComparisons( /// [special]p1). This routine can only be executed just before the /// definition of the class is complete. void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { - if (ClassDecl->needsImplicitDefaultConstructor()) { - ++getASTContext().NumImplicitDefaultConstructors; + // Don't add implicit special members to templated classes. + // FIXME: This means unqualified lookups for 'operator=' within a class + // template don't work properly. + if (!ClassDecl->isDependentType()) { + if (ClassDecl->needsImplicitDefaultConstructor()) { + ++getASTContext().NumImplicitDefaultConstructors; - if (ClassDecl->hasInheritedConstructor()) - DeclareImplicitDefaultConstructor(ClassDecl); - } + if (ClassDecl->hasInheritedConstructor()) + DeclareImplicitDefaultConstructor(ClassDecl); + } - if (ClassDecl->needsImplicitCopyConstructor()) { - ++getASTContext().NumImplicitCopyConstructors; + if (ClassDecl->needsImplicitCopyConstructor()) { + ++getASTContext().NumImplicitCopyConstructors; - // If the properties or semantics of the copy constructor couldn't be - // determined while the class was being declared, force a declaration - // of it now. - if (ClassDecl->needsOverloadResolutionForCopyConstructor() || - ClassDecl->hasInheritedConstructor()) - DeclareImplicitCopyConstructor(ClassDecl); - // For the MS ABI we need to know whether the copy ctor is deleted. A - // prerequisite for deleting the implicit copy ctor is that the class has a - // move ctor or move assignment that is either user-declared or whose - // semantics are inherited from a subobject. FIXME: We should provide a more - // direct way for CodeGen to ask whether the constructor was deleted. - else if (Context.getTargetInfo().getCXXABI().isMicrosoft() && - (ClassDecl->hasUserDeclaredMoveConstructor() || - ClassDecl->needsOverloadResolutionForMoveConstructor() || - ClassDecl->hasUserDeclaredMoveAssignment() || - ClassDecl->needsOverloadResolutionForMoveAssignment())) - DeclareImplicitCopyConstructor(ClassDecl); - } + // If the properties or semantics of the copy constructor couldn't be + // determined while the class was being declared, force a declaration + // of it now. + if (ClassDecl->needsOverloadResolutionForCopyConstructor() || + ClassDecl->hasInheritedConstructor()) + DeclareImplicitCopyConstructor(ClassDecl); + // For the MS ABI we need to know whether the copy ctor is deleted. A + // prerequisite for deleting the implicit copy ctor is that the class has + // a move ctor or move assignment that is either user-declared or whose + // semantics are inherited from a subobject. FIXME: We should provide a + // more direct way for CodeGen to ask whether the constructor was deleted. + else if (Context.getTargetInfo().getCXXABI().isMicrosoft() && + (ClassDecl->hasUserDeclaredMoveConstructor() || + ClassDecl->needsOverloadResolutionForMoveConstructor() || + ClassDecl->hasUserDeclaredMoveAssignment() || + ClassDecl->needsOverloadResolutionForMoveAssignment())) + DeclareImplicitCopyConstructor(ClassDecl); + } - if (getLangOpts().CPlusPlus11 && ClassDecl->needsImplicitMoveConstructor()) { - ++getASTContext().NumImplicitMoveConstructors; + if (getLangOpts().CPlusPlus11 && + ClassDecl->needsImplicitMoveConstructor()) { + ++getASTContext().NumImplicitMoveConstructors; - if (ClassDecl->needsOverloadResolutionForMoveConstructor() || - ClassDecl->hasInheritedConstructor()) - DeclareImplicitMoveConstructor(ClassDecl); - } + if (ClassDecl->needsOverloadResolutionForMoveConstructor() || + ClassDecl->hasInheritedConstructor()) + DeclareImplicitMoveConstructor(ClassDecl); + } - if (ClassDecl->needsImplicitCopyAssignment()) { - ++getASTContext().NumImplicitCopyAssignmentOperators; + if (ClassDecl->needsImplicitCopyAssignment()) { + ++getASTContext().NumImplicitCopyAssignmentOperators; - // If we have a dynamic class, then the copy assignment operator may be - // virtual, so we have to declare it immediately. This ensures that, e.g., - // it shows up in the right place in the vtable and that we diagnose - // problems with the implicit exception specification. - if (ClassDecl->isDynamicClass() || - ClassDecl->needsOverloadResolutionForCopyAssignment() || - ClassDecl->hasInheritedAssignment()) - DeclareImplicitCopyAssignment(ClassDecl); - } + // If we have a dynamic class, then the copy assignment operator may be + // virtual, so we have to declare it immediately. This ensures that, e.g., + // it shows up in the right place in the vtable and that we diagnose + // problems with the implicit exception specification. + if (ClassDecl->isDynamicClass() || + ClassDecl->needsOverloadResolutionForCopyAssignment() || + ClassDecl->hasInheritedAssignment()) + DeclareImplicitCopyAssignment(ClassDecl); + } - if (getLangOpts().CPlusPlus11 && ClassDecl->needsImplicitMoveAssignment()) { - ++getASTContext().NumImplicitMoveAssignmentOperators; + if (getLangOpts().CPlusPlus11 && ClassDecl->needsImplicitMoveAssignment()) { + ++getASTContext().NumImplicitMoveAssignmentOperators; - // Likewise for the move assignment operator. - if (ClassDecl->isDynamicClass() || - ClassDecl->needsOverloadResolutionForMoveAssignment() || - ClassDecl->hasInheritedAssignment()) - DeclareImplicitMoveAssignment(ClassDecl); - } + // Likewise for the move assignment operator. + if (ClassDecl->isDynamicClass() || + ClassDecl->needsOverloadResolutionForMoveAssignment() || + ClassDecl->hasInheritedAssignment()) + DeclareImplicitMoveAssignment(ClassDecl); + } - if (ClassDecl->needsImplicitDestructor()) { - ++getASTContext().NumImplicitDestructors; + if (ClassDecl->needsImplicitDestructor()) { + ++getASTContext().NumImplicitDestructors; - // If we have a dynamic class, then the destructor may be virtual, so we - // have to declare the destructor immediately. This ensures that, e.g., it - // shows up in the right place in the vtable and that we diagnose problems - // with the implicit exception specification. - if (ClassDecl->isDynamicClass() || - ClassDecl->needsOverloadResolutionForDestructor()) - DeclareImplicitDestructor(ClassDecl); + // If we have a dynamic class, then the destructor may be virtual, so we + // have to declare the destructor immediately. This ensures that, e.g., it + // shows up in the right place in the vtable and that we diagnose problems + // with the implicit exception specification. + if (ClassDecl->isDynamicClass() || + ClassDecl->needsOverloadResolutionForDestructor()) + DeclareImplicitDestructor(ClassDecl); + } } // C++2a [class.compare.default]p3: // If the member-specification does not explicitly declare any member or // friend named operator==, an == operator function is declared implicitly - // for each defaulted three-way comparison operator function defined in the - // member-specification + // for each defaulted three-way comparison operator function defined in + // the member-specification // FIXME: Consider doing this lazily. - if (getLangOpts().CPlusPlus2a) { - llvm::SmallVector<FunctionDecl*, 4> DefaultedSpaceships; + // We do this during the initial parse for a class template, not during + // instantiation, so that we can handle unqualified lookups for 'operator==' + // when parsing the template. + if (getLangOpts().CPlusPlus20 && !inTemplateInstantiation()) { + llvm::SmallVector<FunctionDecl *, 4> DefaultedSpaceships; findImplicitlyDeclaredEqualityComparisons(Context, ClassDecl, DefaultedSpaceships); for (auto *FD : DefaultedSpaceships) @@ -9620,19 +9949,17 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { } } -unsigned Sema::ActOnReenterTemplateScope(Scope *S, Decl *D) { +unsigned +Sema::ActOnReenterTemplateScope(Decl *D, + llvm::function_ref<Scope *()> EnterScope) { if (!D) return 0; + AdjustDeclIfTemplate(D); - // The order of template parameters is not important here. All names - // get added to the same scope. + // In order to get name lookup right, reenter template scopes in order from + // outermost to innermost. SmallVector<TemplateParameterList *, 4> ParameterLists; - - if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D)) - D = TD->getTemplatedDecl(); - - if (auto *PSD = dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) - ParameterLists.push_back(PSD->getTemplateParameters()); + DeclContext *LookupDC = dyn_cast<DeclContext>(D); if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) { for (unsigned i = 0; i < DD->getNumTemplateParameterLists(); ++i) @@ -9641,31 +9968,49 @@ unsigned Sema::ActOnReenterTemplateScope(Scope *S, Decl *D) { if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { if (FunctionTemplateDecl *FTD = FD->getDescribedFunctionTemplate()) ParameterLists.push_back(FTD->getTemplateParameters()); - } - } + } else if (VarDecl *VD = dyn_cast<VarDecl>(D)) { + LookupDC = VD->getDeclContext(); - if (TagDecl *TD = dyn_cast<TagDecl>(D)) { + if (VarTemplateDecl *VTD = VD->getDescribedVarTemplate()) + ParameterLists.push_back(VTD->getTemplateParameters()); + else if (auto *PSD = dyn_cast<VarTemplatePartialSpecializationDecl>(D)) + ParameterLists.push_back(PSD->getTemplateParameters()); + } + } else if (TagDecl *TD = dyn_cast<TagDecl>(D)) { for (unsigned i = 0; i < TD->getNumTemplateParameterLists(); ++i) ParameterLists.push_back(TD->getTemplateParameterList(i)); if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(TD)) { if (ClassTemplateDecl *CTD = RD->getDescribedClassTemplate()) ParameterLists.push_back(CTD->getTemplateParameters()); + else if (auto *PSD = dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) + ParameterLists.push_back(PSD->getTemplateParameters()); } } + // FIXME: Alias declarations and concepts. unsigned Count = 0; + Scope *InnermostTemplateScope = nullptr; for (TemplateParameterList *Params : ParameterLists) { - if (Params->size() > 0) - // Ignore explicit specializations; they don't contribute to the template - // depth. - ++Count; + // Ignore explicit specializations; they don't contribute to the template + // depth. + if (Params->size() == 0) + continue; + + InnermostTemplateScope = EnterScope(); for (NamedDecl *Param : *Params) { if (Param->getDeclName()) { - S->AddDecl(Param); + InnermostTemplateScope->AddDecl(Param); IdResolver.AddDecl(Param); } } + ++Count; + } + + // Associate the new template scopes with the corresponding entities. + if (InnermostTemplateScope) { + assert(LookupDC && "no enclosing DeclContext for template lookup"); + EnterTemplatedContext(InnermostTemplateScope, LookupDC); } return Count; @@ -9717,11 +10062,6 @@ void Sema::ActOnDelayedCXXMethodParameter(Scope *S, Decl *ParamD) { ParmVarDecl *Param = cast<ParmVarDecl>(ParamD); - // If this parameter has an unparsed default argument, clear it out - // to make way for the parsed default argument. - if (Param->hasUnparsedDefaultArg()) - Param->setDefaultArg(nullptr); - S->AddDecl(Param); if (Param->getDeclName()) IdResolver.AddDecl(Param); @@ -9855,11 +10195,9 @@ void Sema::CheckConstructor(CXXConstructorDecl *Constructor) { // either there are no other parameters or else all other // parameters have default arguments. if (!Constructor->isInvalidDecl() && - ((Constructor->getNumParams() == 1) || - (Constructor->getNumParams() > 1 && - Constructor->getParamDecl(1)->hasDefaultArg())) && - Constructor->getTemplateSpecializationKind() - != TSK_ImplicitInstantiation) { + Constructor->hasOneParamOrDefaultArgs() && + Constructor->getTemplateSpecializationKind() != + TSK_ImplicitInstantiation) { QualType ParamType = Constructor->getParamDecl(0)->getType(); QualType ClassTy = Context.getTagDeclType(ClassDecl); if (Context.getCanonicalType(ParamType).getUnqualifiedType() == ClassTy) { @@ -9944,12 +10282,12 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R, // declaration. QualType DeclaratorType = GetTypeFromParser(D.getName().DestructorName); if (const TypedefType *TT = DeclaratorType->getAs<TypedefType>()) - Diag(D.getIdentifierLoc(), diag::err_destructor_typedef_name) + Diag(D.getIdentifierLoc(), diag::ext_destructor_typedef_name) << DeclaratorType << isa<TypeAliasDecl>(TT->getDecl()); else if (const TemplateSpecializationType *TST = DeclaratorType->getAs<TemplateSpecializationType>()) if (TST->isTypeAlias()) - Diag(D.getIdentifierLoc(), diag::err_destructor_typedef_name) + Diag(D.getIdentifierLoc(), diag::ext_destructor_typedef_name) << DeclaratorType << 1; // C++ [class.dtor]p2: @@ -10211,7 +10549,7 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R, R = Context.getFunctionType(ConvType, None, Proto->getExtProtoInfo()); // C++0x explicit conversion operators. - if (DS.hasExplicitSpecifier() && !getLangOpts().CPlusPlus2a) + if (DS.hasExplicitSpecifier() && !getLangOpts().CPlusPlus20) Diag(DS.getExplicitSpecLoc(), getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_explicit_conversion_functions @@ -10230,15 +10568,12 @@ Decl *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) { // Make sure we aren't redeclaring the conversion function. QualType ConvType = Context.getCanonicalType(Conversion->getConversionType()); - // C++ [class.conv.fct]p1: // [...] A conversion function is never used to convert a // (possibly cv-qualified) object to the (possibly cv-qualified) // same object type (or a reference to it), to a (possibly // cv-qualified) base class of that type (or a reference to it), // or to (possibly cv-qualified) void. - // FIXME: Suppress this warning if the conversion function ends up being a - // virtual function that overrides a virtual function in a base class. QualType ClassType = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl)); if (const ReferenceType *ConvTypeRef = ConvType->getAs<ReferenceType>()) @@ -10246,6 +10581,8 @@ Decl *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) { if (Conversion->getTemplateSpecializationKind() != TSK_Undeclared && Conversion->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) /* Suppress diagnostics for instantiations. */; + else if (Conversion->size_overridden_methods() != 0) + /* Suppress diagnostics for overriding virtual function in a base class. */; else if (ConvType->isRecordType()) { ConvType = Context.getCanonicalType(ConvType).getUnqualifiedType(); if (ConvType == ClassType) @@ -10920,8 +11257,7 @@ bool Sema::isInitListConstructor(const FunctionDecl *Ctor) { // is of type std::initializer_list<E> or reference to possibly cv-qualified // std::initializer_list<E> for some type E, and either there are no other // parameters or else all other parameters have default arguments. - if (Ctor->getNumParams() < 1 || - (Ctor->getNumParams() > 1 && !Ctor->getParamDecl(1)->hasDefaultArg())) + if (!Ctor->hasOneParamOrDefaultArgs()) return false; QualType ArgType = Ctor->getParamDecl(0)->getType(); @@ -12960,6 +13296,25 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation, } } +void Sema::CheckCompleteDestructorVariant(SourceLocation CurrentLocation, + CXXDestructorDecl *Destructor) { + if (Destructor->isInvalidDecl()) + return; + + CXXRecordDecl *ClassDecl = Destructor->getParent(); + assert(Context.getTargetInfo().getCXXABI().isMicrosoft() && + "implicit complete dtors unneeded outside MS ABI"); + assert(ClassDecl->getNumVBases() > 0 && + "complete dtor only exists for classes with vbases"); + + SynthesizedFunctionScope Scope(*this, Destructor); + + // Add a context note for diagnostics produced after this point. + Scope.addContextNote(CurrentLocation); + + MarkVirtualBaseDestructorsReferenced(Destructor->getLocation(), ClassDecl); +} + /// Perform any semantic analysis which needs to be delayed until all /// pending class member declarations have been parsed. void Sema::ActOnFinishCXXMemberDecls() { @@ -12981,7 +13336,7 @@ void Sema::ActOnFinishCXXNonNestedClass() { SmallVector<CXXMethodDecl*, 4> WorkList; std::swap(DelayedDllExportMemberFunctions, WorkList); for (CXXMethodDecl *M : WorkList) { - DefineImplicitSpecialMember(*this, M, M->getLocation()); + DefineDefaultedFunction(*this, M, M->getLocation()); // Pass the method to the consumer to get emitted. This is not necessary // for explicit instantiation definitions, as they will get emitted @@ -13180,13 +13535,13 @@ buildMemcpyForAssignmentOp(Sema &S, SourceLocation Loc, QualType T, // directly construct UnaryOperators here because semantic analysis // does not permit us to take the address of an xvalue. Expr *From = FromB.build(S, Loc); - From = new (S.Context) UnaryOperator(From, UO_AddrOf, - S.Context.getPointerType(From->getType()), - VK_RValue, OK_Ordinary, Loc, false); + From = UnaryOperator::Create( + S.Context, From, UO_AddrOf, S.Context.getPointerType(From->getType()), + VK_RValue, OK_Ordinary, Loc, false, S.CurFPFeatureOverrides()); Expr *To = ToB.build(S, Loc); - To = new (S.Context) UnaryOperator(To, UO_AddrOf, - S.Context.getPointerType(To->getType()), - VK_RValue, OK_Ordinary, Loc, false); + To = UnaryOperator::Create( + S.Context, To, UO_AddrOf, S.Context.getPointerType(To->getType()), + VK_RValue, OK_Ordinary, Loc, false, S.CurFPFeatureOverrides()); const Type *E = T->getBaseElementTypeUnsafe(); bool NeedsCollectableMemCpy = @@ -13420,18 +13775,17 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T, // Create the comparison against the array bound. llvm::APInt Upper = ArrayTy->getSize().zextOrTrunc(S.Context.getTypeSize(SizeType)); - Expr *Comparison - = new (S.Context) BinaryOperator(IterationVarRefRVal.build(S, Loc), - IntegerLiteral::Create(S.Context, Upper, SizeType, Loc), - BO_NE, S.Context.BoolTy, - VK_RValue, OK_Ordinary, Loc, FPOptions()); + Expr *Comparison = BinaryOperator::Create( + S.Context, IterationVarRefRVal.build(S, Loc), + IntegerLiteral::Create(S.Context, Upper, SizeType, Loc), BO_NE, + S.Context.BoolTy, VK_RValue, OK_Ordinary, Loc, S.CurFPFeatureOverrides()); // 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()); + Expr *Increment = UnaryOperator::Create( + S.Context, IterationVarRef.build(S, Loc), UO_PreInc, SizeType, VK_LValue, + OK_Ordinary, Loc, Upper.isMaxValue(), S.CurFPFeatureOverrides()); // Construct the loop that copies all elements of this array. return S.ActOnForStmt( @@ -13529,8 +13883,10 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { Scope *S = getScopeForContext(ClassDecl); CheckImplicitSpecialMemberDeclaration(S, CopyAssignment); - if (ShouldDeleteSpecialMember(CopyAssignment, CXXCopyAssignment)) + if (ShouldDeleteSpecialMember(CopyAssignment, CXXCopyAssignment)) { + ClassDecl->setImplicitCopyAssignmentIsDeleted(); SetDeclDeleted(CopyAssignment, ClassLoc); + } if (S) PushOnScopeChains(CopyAssignment, S, false); @@ -14642,13 +14998,18 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, MarkFunctionReferenced(ConstructLoc, Constructor); if (getLangOpts().CUDA && !CheckCUDACall(ConstructLoc, Constructor)) return ExprError(); + if (getLangOpts().SYCLIsDevice && + !checkSYCLDeviceFunction(ConstructLoc, Constructor)) + return ExprError(); - return CXXConstructExpr::Create( - Context, DeclInitType, ConstructLoc, Constructor, Elidable, - ExprArgs, HadMultipleCandidates, IsListInitialization, - IsStdInitListInitialization, RequiresZeroInit, - static_cast<CXXConstructExpr::ConstructionKind>(ConstructKind), - ParenRange); + return CheckForImmediateInvocation( + CXXConstructExpr::Create( + Context, DeclInitType, ConstructLoc, Constructor, Elidable, ExprArgs, + HadMultipleCandidates, IsListInitialization, + IsStdInitListInitialization, RequiresZeroInit, + static_cast<CXXConstructExpr::ConstructionKind>(ConstructKind), + ParenRange), + Constructor); } ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { @@ -14726,6 +15087,10 @@ 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. + if (VD->getInit() && VD->getInit()->containsErrors()) + return; CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Record->getDecl()); if (ClassDecl->isInvalidDecl()) return; @@ -14752,10 +15117,13 @@ void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) { // If the destructor is constexpr, check whether the variable has constant // destruction now. - if (Destructor->isConstexpr() && VD->getInit() && - !VD->getInit()->isValueDependent() && VD->evaluateValue()) { + if (Destructor->isConstexpr()) { + bool HasConstantInit = false; + if (VD->getInit() && !VD->getInit()->isValueDependent()) + HasConstantInit = VD->evaluateValue(); SmallVector<PartialDiagnosticAt, 8> Notes; - if (!VD->evaluateDestruction(Notes) && VD->isConstexpr()) { + if (!VD->evaluateDestruction(Notes) && VD->isConstexpr() && + HasConstantInit) { Diag(VD->getLocation(), diag::err_constexpr_var_requires_const_destruction) << VD; for (unsigned I = 0, N = Notes.size(); I != N; ++I) @@ -14855,12 +15223,6 @@ CheckOperatorNewDeleteTypes(Sema &SemaRef, const FunctionDecl *FnDecl, QualType ResultType = FnDecl->getType()->castAs<FunctionType>()->getReturnType(); - // Check that the result type is not dependent. - if (ResultType->isDependentType()) - return SemaRef.Diag(FnDecl->getLocation(), - diag::err_operator_new_delete_dependent_result_type) - << FnDecl->getDeclName() << ExpectedResultType; - // The operator is valid on any address space for OpenCL. if (SemaRef.getLangOpts().OpenCLCPlusPlus) { if (auto *PtrTy = ResultType->getAs<PointerType>()) { @@ -14869,10 +15231,16 @@ CheckOperatorNewDeleteTypes(Sema &SemaRef, const FunctionDecl *FnDecl, } // Check that the result type is what we expect. - if (SemaRef.Context.getCanonicalType(ResultType) != ExpectedResultType) - return SemaRef.Diag(FnDecl->getLocation(), - diag::err_operator_new_delete_invalid_result_type) - << FnDecl->getDeclName() << ExpectedResultType; + if (SemaRef.Context.getCanonicalType(ResultType) != ExpectedResultType) { + // Reject even if the type is dependent; an operator delete function is + // required to have a non-dependent result type. + return SemaRef.Diag( + FnDecl->getLocation(), + ResultType->isDependentType() + ? diag::err_operator_new_delete_dependent_result_type + : diag::err_operator_new_delete_invalid_result_type) + << FnDecl->getDeclName() << ExpectedResultType; + } // A function template must have at least 2 parameters. if (FnDecl->getDescribedFunctionTemplate() && FnDecl->getNumParams() < 2) @@ -14886,13 +15254,7 @@ CheckOperatorNewDeleteTypes(Sema &SemaRef, const FunctionDecl *FnDecl, diag::err_operator_new_delete_too_few_parameters) << FnDecl->getDeclName(); - // Check the first parameter type is not dependent. QualType FirstParamType = FnDecl->getParamDecl(0)->getType(); - if (FirstParamType->isDependentType()) - return SemaRef.Diag(FnDecl->getLocation(), DependentParamTypeDiag) - << FnDecl->getDeclName() << ExpectedFirstParamType; - - // Check that the first parameter type is what we expect. if (SemaRef.getLangOpts().OpenCLCPlusPlus) { // The operator is valid on any address space for OpenCL. if (auto *PtrTy = @@ -14900,10 +15262,18 @@ CheckOperatorNewDeleteTypes(Sema &SemaRef, const FunctionDecl *FnDecl, FirstParamType = RemoveAddressSpaceFromPtr(SemaRef, PtrTy); } } + + // Check that the first parameter type is what we expect. if (SemaRef.Context.getCanonicalType(FirstParamType).getUnqualifiedType() != - ExpectedFirstParamType) - return SemaRef.Diag(FnDecl->getLocation(), InvalidParamTypeDiag) - << FnDecl->getDeclName() << ExpectedFirstParamType; + ExpectedFirstParamType) { + // The first parameter type is not allowed to be dependent. As a tentative + // DR resolution, we allow a dependent parameter type if it is the right + // type anyway, to allow destroying operator delete in class templates. + return SemaRef.Diag(FnDecl->getLocation(), FirstParamType->isDependentType() + ? DependentParamTypeDiag + : InvalidParamTypeDiag) + << FnDecl->getDeclName() << ExpectedFirstParamType; + } return false; } @@ -15442,6 +15812,11 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, !BaseType->isDependentType() && RequireCompleteType(Loc, BaseType, DK)) Invalid = true; + if (!Invalid && Mode != 1 && BaseType->isSizelessType()) { + Diag(Loc, diag::err_catch_sizeless) << (Mode == 2 ? 1 : 0) << BaseType; + Invalid = true; + } + if (!Invalid && !ExDeclType->isDependentType() && RequireNonAbstractType(Loc, ExDeclType, diag::err_abstract_type_in_decl, @@ -16304,9 +16679,16 @@ void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) { Diag(Prev->getLocation().isInvalid() ? DelLoc : Prev->getLocation(), Prev->isImplicit() ? diag::note_previous_implicit_declaration : diag::note_previous_declaration); + // We can't recover from this; the declaration might have already + // been used. + Fn->setInvalidDecl(); + return; } - // If the declaration wasn't the first, we delete the function anyway for - // recovery. + + // To maintain the invariant that functions are only deleted on their first + // declaration, mark the implicitly-instantiated declaration of the + // explicitly-specialized function as deleted instead of marking the + // instantiated redeclaration. Fn = Fn->getCanonicalDecl(); } @@ -16316,9 +16698,6 @@ void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) { Fn->setInvalidDecl(); } - if (Fn->isDeleted()) - return; - // C++11 [basic.start.main]p3: // A program that defines main as deleted [...] is ill-formed. if (Fn->isMain()) @@ -16328,25 +16707,6 @@ void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) { // A deleted function is implicitly inline. Fn->setImplicitlyInline(); Fn->setDeletedAsWritten(); - - // See if we're deleting a function which is already known to override a - // non-deleted virtual function. - if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Fn)) { - bool IssuedDiagnostic = false; - for (const CXXMethodDecl *O : MD->overridden_methods()) { - if (!(*MD->begin_overridden_methods())->isDeleted()) { - if (!IssuedDiagnostic) { - Diag(DelLoc, diag::err_deleted_override) << MD->getDeclName(); - IssuedDiagnostic = true; - } - Diag(O->getLocation(), diag::note_overridden_virtual_function); - } - } - // If this function was implicitly deleted because it was defaulted, - // explain why it was deleted. - if (IssuedDiagnostic && MD->isDefaulted()) - DiagnoseDeletedDefaultedFunction(MD); - } } void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) { @@ -16363,7 +16723,7 @@ void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) { } Diag(DefaultLoc, diag::err_default_special_members) - << getLangOpts().CPlusPlus2a; + << getLangOpts().CPlusPlus20; return; } @@ -16377,7 +16737,7 @@ void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) { (!isa<CXXConstructorDecl>(FD) && FD->getDeclName().getCXXOverloadedOperator() != OO_Equal))) { Diag(DefaultLoc, diag::err_default_special_members) - << getLangOpts().CPlusPlus2a; + << getLangOpts().CPlusPlus20; return; } @@ -16392,7 +16752,7 @@ void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) { // 'operator<=>' when parsing the '<=>' token. if (DefKind.isComparison() && DefKind.asComparison() != DefaultedComparisonKind::ThreeWay) { - Diag(DefaultLoc, getLangOpts().CPlusPlus2a + Diag(DefaultLoc, getLangOpts().CPlusPlus20 ? diag::warn_cxx17_compat_defaulted_comparison : diag::ext_defaulted_comparison); } @@ -16428,10 +16788,12 @@ void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) { if (Primary->getCanonicalDecl()->isDefaulted()) return; + // FIXME: Once we support defining comparisons out of class, check for a + // defaulted comparison here. if (CheckExplicitlyDefaultedSpecialMember(MD, DefKind.asSpecialMember())) MD->setInvalidDecl(); else - DefineImplicitSpecialMember(*this, MD, DefaultLoc); + DefineDefaultedFunction(*this, MD, DefaultLoc); } static void SearchForReturnInStmt(Sema &Self, Stmt *S) { @@ -16743,7 +17105,7 @@ void Sema::MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class, return; // Do not mark as used if compiling for the device outside of the target // region. - if (LangOpts.OpenMP && LangOpts.OpenMPIsDevice && + if (TUKind != TU_Prefix && LangOpts.OpenMP && LangOpts.OpenMPIsDevice && !isInOpenMPDeclareTargetContext() && !isInOpenMPTargetExecutionDirective()) { if (!DefinitionRequired) @@ -17386,3 +17748,50 @@ MSPropertyDecl *Sema::HandleMSProperty(Scope *S, RecordDecl *Record, return NewPD; } + +void Sema::ActOnStartFunctionDeclarationDeclarator( + Declarator &Declarator, unsigned TemplateParameterDepth) { + auto &Info = InventedParameterInfos.emplace_back(); + TemplateParameterList *ExplicitParams = nullptr; + ArrayRef<TemplateParameterList *> ExplicitLists = + Declarator.getTemplateParameterLists(); + if (!ExplicitLists.empty()) { + bool IsMemberSpecialization, IsInvalid; + ExplicitParams = MatchTemplateParametersToScopeSpecifier( + Declarator.getBeginLoc(), Declarator.getIdentifierLoc(), + Declarator.getCXXScopeSpec(), /*TemplateId=*/nullptr, + ExplicitLists, /*IsFriend=*/false, IsMemberSpecialization, IsInvalid, + /*SuppressDiagnostic=*/true); + } + if (ExplicitParams) { + Info.AutoTemplateParameterDepth = ExplicitParams->getDepth(); + for (NamedDecl *Param : *ExplicitParams) + Info.TemplateParams.push_back(Param); + Info.NumExplicitTemplateParams = ExplicitParams->size(); + } else { + Info.AutoTemplateParameterDepth = TemplateParameterDepth; + Info.NumExplicitTemplateParams = 0; + } +} + +void Sema::ActOnFinishFunctionDeclarationDeclarator(Declarator &Declarator) { + auto &FSI = InventedParameterInfos.back(); + if (FSI.TemplateParams.size() > FSI.NumExplicitTemplateParams) { + if (FSI.NumExplicitTemplateParams != 0) { + TemplateParameterList *ExplicitParams = + Declarator.getTemplateParameterLists().back(); + Declarator.setInventedTemplateParameterList( + TemplateParameterList::Create( + Context, ExplicitParams->getTemplateLoc(), + ExplicitParams->getLAngleLoc(), FSI.TemplateParams, + ExplicitParams->getRAngleLoc(), + ExplicitParams->getRequiresClause())); + } else { + Declarator.setInventedTemplateParameterList( + TemplateParameterList::Create( + Context, SourceLocation(), SourceLocation(), FSI.TemplateParams, + SourceLocation(), /*RequiresClause=*/nullptr)); + } + } + InventedParameterInfos.pop_back(); +} |