Tweak the fix to PR8977: an empty expression-list represents value initialization, not default initialization. Fixes PR11712.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@147620 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index e4382ec..07e6c64 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1172,6 +1172,8 @@
"declaration of variable %0 with type %1 requires an initializer">;
def err_auto_new_requires_ctor_arg : Error<
"new expression for type %0 requires a constructor argument">;
+def err_auto_var_init_no_expression : Error<
+ "initializer for variable %0 with type %1 is empty">;
def err_auto_var_init_multiple_expressions : Error<
"initializer for variable %0 with type %1 contains multiple expressions">;
def err_auto_new_ctor_multiple_expressions : Error<
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 46a47a2..56b526b 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -8898,8 +8898,6 @@
MultiExprArg Exprs,
SourceLocation RParenLoc,
bool TypeMayContainAuto) {
- assert(Exprs.size() != 0 && Exprs.get() && "missing expressions");
-
// If there is no declaration, there was an error parsing it. Just ignore
// the initializer.
if (RealDecl == 0)
@@ -8912,9 +8910,18 @@
return;
}
- // C++0x [decl.spec.auto]p6. Deduce the type which 'auto' stands in for.
+ // C++0x [dcl.spec.auto]p6. Deduce the type which 'auto' stands in for.
if (TypeMayContainAuto && VDecl->getType()->getContainedAutoType()) {
- // FIXME: n3225 doesn't actually seem to indicate this is ill-formed
+ if (Exprs.size() == 0) {
+ // It isn't possible to write this directly, but it is possible to
+ // end up in this situation with "auto x(some_pack...);"
+ Diag(LParenLoc, diag::err_auto_var_init_no_expression)
+ << VDecl->getDeclName() << VDecl->getType()
+ << VDecl->getSourceRange();
+ RealDecl->setInvalidDecl();
+ return;
+ }
+
if (Exprs.size() > 1) {
Diag(Exprs.get()[1]->getSourceRange().getBegin(),
diag::err_auto_var_init_multiple_expressions)
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 1f87983..00addc2 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -393,16 +393,15 @@
if (!SemaRef.InstantiateInitializer(D->getInit(), TemplateArgs, LParenLoc,
InitArgs, RParenLoc)) {
bool TypeMayContainAuto = true;
- // Attach the initializer to the declaration, if we have one.
- if (InitArgs.size() == 0)
- SemaRef.ActOnUninitializedDecl(Var, TypeMayContainAuto);
- else if (D->hasCXXDirectInitializer()) {
+ if (D->hasCXXDirectInitializer()) {
// Add the direct initializer to the declaration.
SemaRef.AddCXXDirectInitializerToDecl(Var,
LParenLoc,
move_arg(InitArgs),
RParenLoc,
TypeMayContainAuto);
+ } else if (InitArgs.size() == 0) {
+ SemaRef.ActOnUninitializedDecl(Var, TypeMayContainAuto);
} else {
assert(InitArgs.size() == 1);
Expr *Init = InitArgs.take()[0];
diff --git a/test/CXX/temp/temp.decls/temp.variadic/p4.cpp b/test/CXX/temp/temp.decls/temp.variadic/p4.cpp
index 05e4921..71e6927 100644
--- a/test/CXX/temp/temp.decls/temp.variadic/p4.cpp
+++ b/test/CXX/temp/temp.decls/temp.variadic/p4.cpp
@@ -37,7 +37,8 @@
namespace PR8977 {
struct A { };
template<typename T, typename... Args> void f(Args... args) {
- T t(args...);
+ // An empty expression-list performs value initialization.
+ constexpr T t(args...);
};
template void f<A>();
diff --git a/test/SemaCXX/dependent-auto.cpp b/test/SemaCXX/dependent-auto.cpp
index 1be1566..6d37f7a 100644
--- a/test/SemaCXX/dependent-auto.cpp
+++ b/test/SemaCXX/dependent-auto.cpp
@@ -8,7 +8,7 @@
template<typename ...T>
void f(T ...t) {
- auto x(t...); // expected-error {{requires an initializer}} expected-error {{contains multiple expressions}}
+ auto x(t...); // expected-error {{is empty}} expected-error {{contains multiple expressions}}
only<int> check = x;
}