diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 2e1630827cce3..185ba2f4b4c1d 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -2439,6 +2439,14 @@ class FunctionDecl : public DeclaratorDecl, /// parameters have default arguments (in C++). unsigned getMinRequiredArguments() const; + /// Determine whether this function has a single parameter, or multiple + /// parameters where all but the first have default arguments. + /// + /// This notion is used in the definition of copy/move constructors and + /// initializer list constructors. Note that, unlike getMinRequiredArguments, + /// parameter packs are not treated specially here. + bool hasOneParamOrDefaultArgs() const; + /// Find the source location information for how the type of this function /// was written. May be absent (for example if the function was declared via /// a typedef) and may contain a different type from that of the function diff --git a/clang/include/clang/Sema/Template.h b/clang/include/clang/Sema/Template.h index 47d6143bdc9aa..8166b6cf9b6f0 100644 --- a/clang/include/clang/Sema/Template.h +++ b/clang/include/clang/Sema/Template.h @@ -422,6 +422,9 @@ class VarDecl; NamedDecl * getPartiallySubstitutedPack(const TemplateArgument **ExplicitArgs = nullptr, unsigned *NumExplicitArgs = nullptr) const; + + /// Determine whether D is a pack expansion created in this scope. + bool isLocalPackExpansion(const Decl *D); }; class TemplateDeclInstantiator diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index e6800073ee58d..23547933b88b9 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -3264,13 +3264,27 @@ unsigned FunctionDecl::getMinRequiredArguments() const { if (!getASTContext().getLangOpts().CPlusPlus) return getNumParams(); + // Note that it is possible for a parameter with no default argument to + // follow a parameter with a default argument. unsigned NumRequiredArgs = 0; - for (auto *Param : parameters()) - if (!Param->isParameterPack() && !Param->hasDefaultArg()) - ++NumRequiredArgs; + unsigned MinParamsSoFar = 0; + for (auto *Param : parameters()) { + if (!Param->isParameterPack()) { + ++MinParamsSoFar; + if (!Param->hasDefaultArg()) + NumRequiredArgs = MinParamsSoFar; + } + } return NumRequiredArgs; } +bool FunctionDecl::hasOneParamOrDefaultArgs() const { + return getNumParams() == 1 || + (getNumParams() > 1 && + std::all_of(param_begin() + 1, param_end(), + [](ParmVarDecl *P) { return P->hasDefaultArg(); })); +} + /// The combination of the extern and inline keywords under MSVC forces /// the function to be required. /// diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 96e63416073ad..5412aa7ed5e04 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -2549,11 +2549,11 @@ CXXConstructorDecl *CXXConstructorDecl::getTargetConstructor() const { } bool CXXConstructorDecl::isDefaultConstructor() const { - // C++ [class.ctor]p5: - // A default constructor for a class X is a constructor of class - // X that can be called without an argument. - return (getNumParams() == 0) || - (getNumParams() > 0 && getParamDecl(0)->hasDefaultArg()); + // C++ [class.default.ctor]p1: + // A default constructor for a class X is a constructor of class X for + // which each parameter that is not a function parameter pack has a default + // argument (including the case of a constructor with no parameters) + return getMinRequiredArguments() == 0; } bool @@ -2564,7 +2564,7 @@ CXXConstructorDecl::isCopyConstructor(unsigned &TypeQuals) const { bool CXXConstructorDecl::isMoveConstructor(unsigned &TypeQuals) const { return isCopyOrMoveConstructor(TypeQuals) && - getParamDecl(0)->getType()->isRValueReferenceType(); + getParamDecl(0)->getType()->isRValueReferenceType(); } /// Determine whether this is a copy or move constructor. @@ -2579,10 +2579,8 @@ bool CXXConstructorDecl::isCopyOrMoveConstructor(unsigned &TypeQuals) const { // first parameter is of type X&&, const X&&, volatile X&&, or // const volatile X&&, and either there are no other parameters or else // all other parameters have default arguments. - if ((getNumParams() < 1) || - (getNumParams() > 1 && !getParamDecl(1)->hasDefaultArg()) || - (getPrimaryTemplate() != nullptr) || - (getDescribedFunctionTemplate() != nullptr)) + if (!hasOneParamOrDefaultArgs() || getPrimaryTemplate() != nullptr || + getDescribedFunctionTemplate() != nullptr) return false; const ParmVarDecl *Param = getParamDecl(0); @@ -2619,18 +2617,16 @@ bool CXXConstructorDecl::isConvertingConstructor(bool AllowExplicit) const { if (isExplicit() && !AllowExplicit) return false; - return (getNumParams() == 0 && - getType()->castAs()->isVariadic()) || - (getNumParams() == 1) || - (getNumParams() > 1 && - (getParamDecl(1)->hasDefaultArg() || - getParamDecl(1)->isParameterPack())); + // FIXME: This has nothing to do with the definition of converting + // constructor, but is convenient for how we use this function in overload + // resolution. + return getNumParams() == 0 + ? getType()->castAs()->isVariadic() + : getMinRequiredArguments() <= 1; } bool CXXConstructorDecl::isSpecializationCopyingObject() const { - if ((getNumParams() < 1) || - (getNumParams() > 1 && !getParamDecl(1)->hasDefaultArg()) || - (getDescribedFunctionTemplate() != nullptr)) + if (!hasOneParamOrDefaultArgs() || getDescribedFunctionTemplate() != nullptr) return false; const ParmVarDecl *Param = getParamDecl(0); diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index cedd9437e0012..a137e6c0b7457 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 #include @@ -304,18 +305,22 @@ Sema::ActOnParamDefaultArgument(Decl *param, SourceLocation EqualLoc, ParmVarDecl *Param = cast(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,17 +329,18 @@ 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; } // Check that the default argument is well-formed CheckDefaultArgumentVisitor DefaultArgChecker(DefaultArg, this); - if (DefaultArgChecker.Visit(DefaultArg)) { - Param->setInvalidDecl(); - return; - } + if (DefaultArgChecker.Visit(DefaultArg)) + return Fail(); - SetParamDefaultArgument(Param, DefaultArg, EqualLoc); + if (SetParamDefaultArgument(Param, DefaultArg, EqualLoc)) + return Fail(); } /// ActOnParamUnparsedDefaultArgument - We've seen a default @@ -419,14 +425,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++ @@ -1528,25 +1529,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 +1566,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); - } } } } @@ -9973,11 +9968,6 @@ void Sema::ActOnDelayedCXXMethodParameter(Scope *S, Decl *ParamD) { ParmVarDecl *Param = cast(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); @@ -10111,11 +10101,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) { @@ -11175,8 +11163,7 @@ bool Sema::isInitListConstructor(const FunctionDecl *Ctor) { // is of type std::initializer_list or reference to possibly cv-qualified // std::initializer_list 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(); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 5e8b1d8a37cc4..3c07b7d35b87c 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -5502,6 +5502,15 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, bool Sema::CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD, ParmVarDecl *Param) { if (Param->hasUnparsedDefaultArg()) { + // If we've already cleared out the location for the default argument, + // that means we're parsing it right now. + if (!UnparsedDefaultArgLocs.count(Param)) { + Diag(Param->getBeginLoc(), diag::err_recursive_default_argument) << FD; + Diag(CallLoc, diag::note_recursive_default_argument_used_here); + Param->setInvalidDecl(); + return true; + } + Diag(CallLoc, diag::err_use_of_default_argument_to_function_declared_later) << FD << cast(FD->getDeclContext())->getDeclName(); @@ -5588,13 +5597,7 @@ bool Sema::CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD, } } - // If the default argument expression is not set yet, we are building it now. - if (!Param->hasInit()) { - Diag(Param->getBeginLoc(), diag::err_recursive_default_argument) << FD; - Diag(CallLoc, diag::note_recursive_default_argument_used_here); - Param->setInvalidDecl(); - return true; - } + assert(Param->hasInit() && "default argument but no initializer?"); // If the default expression creates temporaries, we need to // push them to the current stack of expression temporaries so they'll @@ -5627,6 +5630,7 @@ bool Sema::CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD, ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD, ParmVarDecl *Param) { + assert(Param->hasDefaultArg() && "can't build nonexistent default arg"); if (CheckCXXDefaultArgExpr(CallLoc, FD, Param)) return ExprError(); return CXXDefaultArgExpr::Create(Context, CallLoc, Param, CurContext); diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 1aef43614d99e..9739e1511039f 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -6511,6 +6511,8 @@ static bool convertArgsForAvailabilityChecks( if (!Function->isVariadic() && Args.size() < Function->getNumParams()) { for (unsigned i = Args.size(), e = Function->getNumParams(); i != e; ++i) { ParmVarDecl *P = Function->getParamDecl(i); + if (!P->hasDefaultArg()) + return false; ExprResult R = S.BuildCXXDefaultArgExpr(CallLoc, Function, P); if (R.isInvalid()) return false; diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 4b6b92ccab2c5..0cb50b3ea3687 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -3609,6 +3609,13 @@ void LocalInstantiationScope::MakeInstantiatedLocalArgPack(const Decl *D) { ArgumentPacks.push_back(Pack); } +bool LocalInstantiationScope::isLocalPackExpansion(const Decl *D) { + for (DeclArgumentPack *Pack : ArgumentPacks) + if (std::find(Pack->begin(), Pack->end(), D) != Pack->end()) + return true; + return false; +} + void LocalInstantiationScope::SetPartiallySubstitutedPack(NamedDecl *Pack, const TemplateArgument *ExplicitArgs, unsigned NumExplicitArgs) { diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp old mode 100755 new mode 100644 diff --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx03-extra-copy.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx03-extra-copy.cpp index e3190245d240f..9a435fc5b5eff 100644 --- a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx03-extra-copy.cpp +++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx03-extra-copy.cpp @@ -42,8 +42,8 @@ struct X4 { // Check for "dangerous" default arguments that could cause recursion. struct X5 { - X5(); // expected-note {{requires 0 arguments}} - X5(const X5&, const X5& = X5()); // expected-warning{{no viable constructor copying parameter of type 'X5'}} expected-note {{requires 2 arguments}} + X5(); + X5(const X5&, const X5& = X5()); // expected-error {{recursive evaluation of default argument}} expected-note {{used here}} }; void g1(const X1&); @@ -57,7 +57,7 @@ void test() { g2(X2()); // expected-warning{{C++98 requires an accessible copy constructor for class 'X2' when binding a reference to a temporary; was private}} g3(X3()); // expected-warning{{no viable constructor copying parameter of type 'X3'}} g4(X4()); - g5(X5()); // Generates a warning in the default argument. + g5(X5()); } // Check that unavailable copy constructors still cause SFINAE failures. diff --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx0x-no-extra-copy.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx0x-no-extra-copy.cpp index 27eb6d1c078f2..9095a7c43465c 100644 --- a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx0x-no-extra-copy.cpp +++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx0x-no-extra-copy.cpp @@ -37,16 +37,23 @@ struct X4 { X4(const X4&, T = get_value_badly()); }; +struct X5 { + X5(); + X5(const X5&, const X5& = X5()); +}; + void g1(const X1&); void g2(const X2&); void g3(const X3&); void g4(const X4&); +void g5(const X5&); void test() { g1(X1()); g2(X2()); g3(X3()); g4(X4()); + g5(X5()); } // Check that unavailable copy constructors do not cause SFINAE failures. diff --git a/clang/test/CXX/drs/dr0xx.cpp b/clang/test/CXX/drs/dr0xx.cpp index 53bd6f3f05382..d998114442be4 100644 --- a/clang/test/CXX/drs/dr0xx.cpp +++ b/clang/test/CXX/drs/dr0xx.cpp @@ -316,15 +316,16 @@ namespace dr25 { // dr25: yes namespace dr26 { // dr26: yes struct A { A(A, const A & = A()); }; // expected-error {{must pass its first argument by reference}} struct B { - B(); // expected-note 0-1{{candidate}} + B(); + // FIXME: In C++98, we diagnose this twice. B(const B &, B = B()); #if __cplusplus <= 201402L - // expected-error@-2 {{no matching constructor}} expected-note@-2 {{candidate}} expected-note@-2 {{here}} + // expected-error@-2 1+{{recursive evaluation of default argument}} expected-note@-2 1+{{used here}} #endif }; struct C { static C &f(); - C(const C &, C = f()); // expected-error {{no matching constructor}} expected-note {{candidate}} expected-note {{here}} + C(const C &, C = f()); // expected-error {{recursive evaluation of default argument}} expected-note {{used here}} }; } diff --git a/clang/test/CXX/drs/dr1xx.cpp b/clang/test/CXX/drs/dr1xx.cpp index 1e78c03be8abd..afa26f771eecd 100644 --- a/clang/test/CXX/drs/dr1xx.cpp +++ b/clang/test/CXX/drs/dr1xx.cpp @@ -398,7 +398,7 @@ namespace dr136 { // dr136: 3.4 void q() { j(A(), A()); // ok, has default argument } - extern "C" void k(int, int, int, int); // expected-note {{previous declaration is here}} + extern "C" void k(int, int, int, int); // expected-note 2{{previous declaration is here}} namespace NSA { struct A { friend void dr136::k(int, int, int, int = 0); // expected-error {{friend declaration specifying a default argument must be the only declaration}} @@ -406,7 +406,7 @@ namespace dr136 { // dr136: 3.4 } namespace NSB { struct A { - friend void dr136::k(int, int, int = 0, int); // expected-error {{missing default argument on parameter}} + friend void dr136::k(int, int, int = 0, int); // expected-error {{missing default argument on parameter}} expected-error {{must be the only declaration}} }; } struct B { diff --git a/clang/test/CXX/drs/dr22xx.cpp b/clang/test/CXX/drs/dr22xx.cpp index 8896281e9ca4a..91be4b53cb47a 100644 --- a/clang/test/CXX/drs/dr22xx.cpp +++ b/clang/test/CXX/drs/dr22xx.cpp @@ -35,3 +35,91 @@ namespace dr2292 { // dr2292: 9 } #endif } + +namespace dr2233 { // dr2233: 11 +#if __cplusplus >= 201103L +template +void f(int i = 0, T... args) {} + +template +void g(int i = 0, T... args, T... args2) {} + +template +void h(int i = 0, T... args, int j = 1) {} + +template +void i(int i = 0, T... args, int j = 1, U... args2) {} + +template +void j(int i = 0, Ts... ts) {} + +template <> +void j(int i, int j) {} + +template +void j(int, int, int); + +extern template +void j(int, int, int, int); + +// PR23029 +// Ensure instantiating the templates works. +void use() { + f(); + f(0, 1); + f(1, 2); + g(1, 2, 3); + h(0, 1); + i(); + i(3); + i(3, 2); + i(3, 2, 1); + i(1, 2, 3, 4, 5); + j(); + j(1); + j(1, 2); + j(1, 2); +} + +namespace MultilevelSpecialization { + template struct A { + template void f(int i = 0, int (&... arr)[V]); + }; + template<> template<> + void A::f<1, 1>(int i, int (&arr1a)[1], int (&arr2a)[1]) {} + + // FIXME: I believe this example is valid, at least up to the first explicit + // specialization, but Clang can't cope with explicit specializations that + // expand packs into a sequence of parameters. If we ever start accepting + // that, we'll need to decide whether it's OK for arr1a to be missing its + // default argument -- how far back do we look when determining whether a + // parameter was expanded from a pack? + // -- zygoloid 2020-06-02 + template struct B { + template void f(int i = 0, int (&... arr)[V]); + }; + template<> template + void B::f(int i, int (&arr1)[a], int (&arr2)[b]) {} // expected-error {{does not match}} + template<> template<> + void B::f<1, 1>(int i, int (&arr1a)[1], int (&arr2a)[1]) {} +} + +namespace CheckAfterMerging1 { + template void f() { + void g(int, int = 0); + void g(int = 0, T...); + g(); + } + void h() { f(); } +} + +namespace CheckAfterMerging2 { + template void f() { + void g(int = 0, T...); + void g(int, int = 0); + g(); + } + void h() { f(); } +} +#endif +} // namespace dr2233 diff --git a/clang/test/CXX/drs/dr7xx.cpp b/clang/test/CXX/drs/dr7xx.cpp index 147560d3037b9..dc1d7e86c58bd 100644 --- a/clang/test/CXX/drs/dr7xx.cpp +++ b/clang/test/CXX/drs/dr7xx.cpp @@ -219,16 +219,4 @@ namespace dr727 { // dr727: partial Collision c; // expected-note {{in instantiation of}} } -namespace dr777 { // dr777: 3.7 -#if __cplusplus >= 201103L -template -void f(int i = 0, T ...args) {} -void ff() { f(); } - -template -void g(int i = 0, T ...args, T ...args2) {} - -template -void h(int i = 0, T ...args, int j = 1) {} -#endif -} +// dr777 superseded by dr2233 diff --git a/clang/test/CXX/expr/expr.post/expr.call/p4.cpp b/clang/test/CXX/expr/expr.post/expr.call/p4.cpp new file mode 100644 index 0000000000000..837e823159ae4 --- /dev/null +++ b/clang/test/CXX/expr/expr.post/expr.call/p4.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -verify %s + +void a(int x = 0, int y); // #1 expected-error {{missing default argument on parameter 'y'}} +void b() { + a(); // expected-error {{no matching function}} expected-note@#1 {{requires 2 arguments, but 0 were provided}} + a(0); // expected-error {{no matching function}} expected-note@#1 {{requires 2 arguments, but 1 was provided}} + a(0, 0); +} + +void a(int x, int y = 0); +void c() { + a(); + a(0); + a(0, 0); +} + +template void f(int x = 0, T ...); // #2 +void g() { + f(); // expected-error {{no matching function}} expected-note@#2 {{requires 2 arguments, but 0 were provided}} + f(0); // expected-error {{no matching function}} expected-note@#2 {{requires 2 arguments, but 1 was provided}} + f(0, 0); +} diff --git a/clang/test/SemaCXX/abstract.cpp b/clang/test/SemaCXX/abstract.cpp index ffd36be5b7970..1fda21caea49f 100644 --- a/clang/test/SemaCXX/abstract.cpp +++ b/clang/test/SemaCXX/abstract.cpp @@ -258,7 +258,8 @@ namespace test5 { struct A { A(int); virtual ~A() = 0; }; // expected-note {{pure virtual method}} const A &a = 0; // expected-error {{abstract class}} void f(const A &a = 0); // expected-error {{abstract class}} - void g() { f(0); } // expected-error {{abstract class}} + void g(const A &a); + void h() { g(0); } // expected-error {{abstract class}} } // PR9247: Crash on invalid in clang::Sema::ActOnFinishCXXMemberSpecification diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp index a8ded62e88ee7..084e9701464d2 100644 --- a/clang/test/SemaCXX/constant-expression-cxx11.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp @@ -2046,9 +2046,9 @@ namespace BadDefaultInit { // FIXME: The "constexpr constructor must initialize all members" diagnostic // here is bogus (we discard the k(k) initializer because the parameter 'k' // has been marked invalid). - struct B { // expected-note 2{{candidate}} - constexpr B( // expected-warning {{initialize all members}} expected-note {{candidate}} - int k = X::n) : // expected-error {{no matching constructor}} + struct B { + constexpr B( // expected-warning {{initialize all members}} + int k = X::n) : // expected-error {{default argument to function 'B' that is declared later}} expected-note {{here}} k(k) {} int k; // expected-note {{not initialized}} }; diff --git a/clang/test/SemaCXX/decl-init-ref.cpp b/clang/test/SemaCXX/decl-init-ref.cpp index fb5ca8c1491f2..f515630d3f5e1 100644 --- a/clang/test/SemaCXX/decl-init-ref.cpp +++ b/clang/test/SemaCXX/decl-init-ref.cpp @@ -40,8 +40,8 @@ namespace PR16502 { namespace IncompleteTest { struct String; // expected-error@+1 {{reference to incomplete type 'const IncompleteTest::String' could not bind to an lvalue of type 'const char [1]'}} - void takeString(const String& = "") {} // expected-note {{passing argument to parameter here}} expected-note {{candidate function}} + void takeString(const String& = "") {} // expected-note {{passing argument to parameter here}} void test() { - takeString(); // expected-error {{no matching function for call}} + takeString(); } } diff --git a/clang/test/SemaCXX/implicit-exception-spec.cpp b/clang/test/SemaCXX/implicit-exception-spec.cpp index 8545e8422b2a5..a15df0675a271 100644 --- a/clang/test/SemaCXX/implicit-exception-spec.cpp +++ b/clang/test/SemaCXX/implicit-exception-spec.cpp @@ -54,10 +54,12 @@ namespace ExceptionSpecification { } namespace DefaultArgument { + // FIXME: We should detect and diagnose the cyclic dependence of + // noexcept(Default()) on itself here. struct Default { struct T { - T(int = ExceptionIf'}} expected-note {{to match this '<'}} - } t; // expected-note {{has no default constructor}} + T(int = ExceptionIf::f()); + } t; }; } diff --git a/clang/test/SemaCXX/warn-bool-conversion.cpp b/clang/test/SemaCXX/warn-bool-conversion.cpp index 6eca171f254e1..7b671c52b5b9c 100644 --- a/clang/test/SemaCXX/warn-bool-conversion.cpp +++ b/clang/test/SemaCXX/warn-bool-conversion.cpp @@ -11,13 +11,17 @@ int* j = false; #endif #if __cplusplus <= 199711L -// expected-warning@+6 {{initialization of pointer of type 'int *' to null from a constant boolean expression}} +// expected-warning@+5 {{initialization of pointer of type 'int *' to null from a constant boolean expression}} #else -// expected-error@+4 {{cannot initialize a parameter of type 'int *' with an rvalue of type 'bool'}} -// expected-note@+3 {{passing argument to parameter 'j' here}} -// expected-note@+2 6 {{candidate function not viable: requires 2 arguments, but 1 was provided}} +// expected-error@+3 {{cannot initialize a parameter of type 'int *' with an rvalue of type 'bool'}} +// expected-note@+2 {{passing argument to parameter 'j' here}} #endif -void foo(int* i, int *j=(false)) +void bar(int *j = false); + +#if __cplusplus > 199711L +// expected-note@+2 4{{candidate function not viable: no known conversion}} +#endif +void foo(int *i) { foo(false); #if __cplusplus <= 199711L @@ -26,19 +30,8 @@ void foo(int* i, int *j=(false)) // expected-error@-4 {{no matching function for call to 'foo'}} #endif - foo((int*)false); -#if __cplusplus <= 199711L -// no-warning: explicit cast -#else -// expected-error@-4 {{no matching function for call to 'foo'}} -#endif - - foo(0); -#if __cplusplus <= 199711L -// no-warning: not a bool, even though its convertible to bool -#else -// expected-error@-4 {{no matching function for call to 'foo'}} -#endif + foo((int*)false); // OK: explicit cast + foo(0); // OK: not a bool, even though it's convertible to bool foo(false == true); #if __cplusplus <= 199711L diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html index defdf677ae018..1a06a85d09122 100755 --- a/clang/www/cxx_dr_status.html +++ b/clang/www/cxx_dr_status.html @@ -4681,7 +4681,7 @@

C++ defect report implementation status

777 CD2 Default arguments and parameter packs - Clang 3.7 + Superseded by 2233 778 @@ -13213,7 +13213,7 @@

C++ defect report implementation status

2233 DRWP Function parameter packs following default arguments - Unknown + Clang 11 2234