[PATCH] D79800: [Sema] Remove default values for arguments prior to a parameter pack if the pack is used
Raul Tambre via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Tue May 12 12:55:02 PDT 2020
tambre created this revision.
tambre added reviewers: rsmith, rjmccall.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
When a parameter pack is expanded the expanded parameters don't have default values.
Thus if a parameter pack is expanded after any arguments with a default value, the function is incorrectly rejected in CheckCXXDefaultArguments().
Fix this by removing default arguments for prior parameters if a parameter pack is expanded.
Fixes PR23029.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D79800
Files:
clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
clang/test/CXX/drs/dr7xx.cpp
Index: clang/test/CXX/drs/dr7xx.cpp
===================================================================
--- clang/test/CXX/drs/dr7xx.cpp
+++ clang/test/CXX/drs/dr7xx.cpp
@@ -230,5 +230,12 @@
template <typename... T>
void h(int i = 0, T ...args, int j = 1) {}
+
+// PR23029
+// Ensure passing parameters using the parameter packs actually works.
+void use() {
+ f(0, 1);
+ h(0, 1);
+}
#endif
}
Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
===================================================================
--- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1974,6 +1974,54 @@
TemplateArgumentList::CreateCopy(SemaRef.Context,
Innermost),
/*InsertPos=*/nullptr);
+
+ // Parameter packs are allowed after parameters with default values.
+ // If the specialized Function has more parameters than the TemplatedDecl
+ // then the default values aren't used and the parameter pack is used and we
+ // need to remove default values from previous parameters to prevent it
+ // being diagnosed as invalid code due to the expanded parameter lacking
+ // default values.
+ FunctionDecl *TemplatedDecl = FunctionTemplate->getTemplatedDecl();
+ unsigned NumTemplatedParams = TemplatedDecl->getNumParams();
+
+ if (Function->getNumParams() >= NumTemplatedParams) {
+ unsigned FirstDefault = 0;
+ unsigned LastDefault = 0;
+ bool FoundDefault = false;
+ bool RemoveDefaults = false;
+
+ // Find the FirstDefault up to LastDefault that need to be removed.
+ // We don't remove if the code's invalid, i.e. a default value missing on
+ // a regular parameter if there's any with a default value before.
+ for (unsigned p = 0; p < NumTemplatedParams; ++p) {
+ ParmVarDecl *Param = TemplatedDecl->getParamDecl(p);
+
+ if (FoundDefault) {
+ if (Param->isParameterPack()) {
+ RemoveDefaults = true;
+ LastDefault = p;
+ break;
+ }
+
+ // If we encounter a regular parameter with no default value after
+ // we've encountered any with a default, then this is invalid code and
+ // we bail out. This is diagnosed later in CheckCXXDefaultArguments().
+ if (!Param->hasDefaultArg())
+ break;
+ } else if (Param->hasDefaultArg()) {
+ FirstDefault = p;
+ FoundDefault = true;
+ }
+ }
+
+ // Remove default arguments if this is valid code.
+ if (RemoveDefaults) {
+ for (unsigned p = FirstDefault; p < LastDefault; ++p) {
+ ParmVarDecl *Param = Function->getParamDecl(p);
+ Param->setDefaultArg(nullptr);
+ }
+ }
+ }
} else if (isFriend && D->isThisDeclarationADefinition()) {
// Do not connect the friend to the template unless it's actually a
// definition. We don't want non-template functions to be marked as being
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D79800.263496.patch
Type: text/x-patch
Size: 3081 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20200512/3e50c19b/attachment.bin>
More information about the cfe-commits
mailing list