[clang] c56975e - Fix template instantiation of a non-dependent call to an inherited
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Mon Apr 6 19:20:36 PDT 2020
Author: Richard Smith
Date: 2020-04-06T19:20:30-07:00
New Revision: c56975e299e17a503066c98a3afaf02c5b231f9e
URL: https://github.com/llvm/llvm-project/commit/c56975e299e17a503066c98a3afaf02c5b231f9e
DIFF: https://github.com/llvm/llvm-project/commit/c56975e299e17a503066c98a3afaf02c5b231f9e.diff
LOG: Fix template instantiation of a non-dependent call to an inherited
constructor with default arguments.
We used to try to rebuild the call as a call to the faked-up inherited
constructor, which is only a placeholder and lacks (for example) default
arguments. Instead, build the call by reference to the original
constructor.
In passing, add a note to say where a call that recursively uses a
default argument from within itself occurs. This is usually pretty
obvious, but still at least somewhat useful, and would have saved
significant debugging time for this particular bug.
Added:
Modified:
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/Sema/SemaExpr.cpp
clang/lib/Sema/TreeTransform.h
clang/test/SemaCXX/default2.cpp
clang/test/SemaTemplate/instantiate-init.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 6ccb1c4af951..148f23f362dc 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3952,6 +3952,8 @@ def err_use_of_default_argument_to_function_declared_later : Error<
def note_default_argument_declared_here : Note<
"default argument declared here">;
def err_recursive_default_argument : Error<"recursive evaluation of default argument">;
+def note_recursive_default_argument_used_here : Note<
+ "default argument used here">;
def ext_param_promoted_not_compatible_with_prototype : ExtWarn<
"%
diff {promoted type $ of K&R function parameter is not compatible with the "
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index b311aad84816..a4f9c22138ee 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -5284,6 +5284,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;
}
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 1f88f9c57465..e9f4b11ca7bb 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -3028,9 +3028,14 @@ class TreeTransform {
bool RequiresZeroInit,
CXXConstructExpr::ConstructionKind ConstructKind,
SourceRange ParenRange) {
+ // Reconstruct the constructor we originally found, which might be
+ //
diff erent if this is a call to an inherited constructor.
+ CXXConstructorDecl *FoundCtor = Constructor;
+ if (Constructor->isInheritingConstructor())
+ FoundCtor = Constructor->getInheritedConstructor().getConstructor();
+
SmallVector<Expr*, 8> ConvertedArgs;
- if (getSema().CompleteConstructorCall(Constructor, Args, Loc,
- ConvertedArgs))
+ if (getSema().CompleteConstructorCall(FoundCtor, Args, Loc, ConvertedArgs))
return ExprError();
return getSema().BuildCXXConstructExpr(Loc, T, Constructor,
diff --git a/clang/test/SemaCXX/default2.cpp b/clang/test/SemaCXX/default2.cpp
index 8f77f300572b..4c8e8ce6941a 100644
--- a/clang/test/SemaCXX/default2.cpp
+++ b/clang/test/SemaCXX/default2.cpp
@@ -130,5 +130,8 @@ template <int I1 = I2, int I2 = 1> struct T {}; // expected-error-re {{use of u
T<0, 1> t;
struct PR28105 {
- PR28105 (int = 0, int = 0, PR28105 = 0); // expected-error{{recursive evaluation of default argument}}
+ PR28105 (int = 0, int = 0,
+ PR28105 // expected-error{{recursive evaluation of default argument}}
+ =
+ 0); // expected-note {{default argument used here}}
};
diff --git a/clang/test/SemaTemplate/instantiate-init.cpp b/clang/test/SemaTemplate/instantiate-init.cpp
index 99b29c77d55a..6a4f65095dd5 100644
--- a/clang/test/SemaTemplate/instantiate-init.cpp
+++ b/clang/test/SemaTemplate/instantiate-init.cpp
@@ -1,5 +1,13 @@
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+namespace std {
+ template<typename T> struct initializer_list {
+ T *p;
+ __SIZE_TYPE__ n;
+ initializer_list(T*, __SIZE_TYPE__);
+ };
+}
+
struct X0 { // expected-note 8{{candidate}}
X0(int*, float*); // expected-note 4{{candidate}}
};
@@ -158,3 +166,15 @@ namespace InitListUpdate {
void g(AA, AA);
void h() { f<1, 2>(); } // expected-note {{instantiation of}}
}
+
+namespace RebuildStdInitList {
+ struct A { A(std::initializer_list<int>, int = 0) {} };
+ struct B : A { using A::A; };
+ struct PES { PES(B); };
+
+ // Check we can rebuild the use of the default argument here. This requires
+ // going to the original (base class) constructor, because we don't copy
+ // default arguments onto our fake derived class inherited constructors.
+ template<typename U> void f() { PES({1, 2, 3}); }
+ void g() { f<int>(); }
+}
More information about the cfe-commits
mailing list