summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Wennborg <hans@hanshq.net>2015-02-11 03:32:18 +0000
committerHans Wennborg <hans@hanshq.net>2015-02-11 03:32:18 +0000
commitf06a0c83eb2f36bf182224a127ad378f42ab5094 (patch)
treec567cf7b649ba868b6b79bf400283cd91e5d49bb
parent530687c93204132bf1fb29a8c8e227a1eb3f950e (diff)
Merging r228792:
------------------------------------------------------------------------ r228792 | rsmith | 2015-02-10 18:41:33 -0800 (Tue, 10 Feb 2015) | 5 lines Add a warning for direct-list-initialization of a variable with a deduced type (or of a lambda init-capture, which is sort-of such a variable). The semantics of such constructs will change when we implement N3922, so we intend to warn on this in Clang 3.6 then change the semantics in Clang 3.7. ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/cfe/branches/release_36@228799 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Basic/DiagnosticGroups.td3
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td4
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td4
-rw-r--r--lib/Parse/ParseExprCXX.cpp11
-rw-r--r--lib/Sema/SemaDecl.cpp8
-rw-r--r--test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp4
-rw-r--r--test/Parser/cxx0x-lambda-expressions.cpp2
-rw-r--r--test/Parser/objcxx0x-lambda-expressions.mm2
-rw-r--r--test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp1
9 files changed, 32 insertions, 7 deletions
diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td
index 5edd3ddbc8..2681ada248 100644
--- a/include/clang/Basic/DiagnosticGroups.td
+++ b/include/clang/Basic/DiagnosticGroups.td
@@ -749,3 +749,6 @@ def SerializedDiagnostics : DiagGroup<"serialized-diagnostics">;
// A warning group for warnings about code that clang accepts when
// compiling CUDA C/C++ but which is not compatible with the CUDA spec.
def CudaCompat : DiagGroup<"cuda-compat">;
+
+// A warning group for things that will change semantics in the future.
+def FutureCompat : DiagGroup<"future-compat">;
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index 239d4d20bb..eca5f13811 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -802,6 +802,10 @@ def warn_cxx98_compat_lambda : Warning<
def err_lambda_missing_parens : Error<
"lambda requires '()' before %select{'mutable'|return type|"
"attribute specifier}0">;
+def warn_init_capture_direct_list_init : Warning<
+ "direct list initialization of a lambda init-capture will change meaning in "
+ "a future version of Clang; insert an '=' to avoid a change in behavior">,
+ InGroup<FutureCompat>;
// Availability attribute
def err_expected_version : Error<
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 2afe77055b..b173d82a31 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1635,6 +1635,10 @@ def err_auto_var_init_multiple_expressions : Error<
def err_auto_var_init_paren_braces : Error<
"cannot deduce type for variable %0 with type %1 from "
"parenthesized initializer list">;
+def warn_auto_var_direct_list_init : Warning<
+ "direct list initialization of a variable with a deduced type will change "
+ "meaning in a future version of Clang; insert an '=' to avoid a change in "
+ "behavior">, InGroup<FutureCompat>;
def err_auto_new_ctor_multiple_expressions : Error<
"new expression for type %0 contains multiple constructor arguments">;
def err_auto_missing_trailing_return : Error<
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 355503caa9..67496edf8c 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -894,11 +894,16 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
// to save the necessary state, and restore it later.
EnterExpressionEvaluationContext EC(Actions,
Sema::PotentiallyEvaluated);
- TryConsumeToken(tok::equal);
+ bool HadEquals = TryConsumeToken(tok::equal);
- if (!SkippedInits)
+ if (!SkippedInits) {
+ // Warn on constructs that will change meaning when we implement N3922
+ if (!HadEquals && Tok.is(tok::l_brace)) {
+ Diag(Tok, diag::warn_init_capture_direct_list_init)
+ << FixItHint::CreateInsertion(Tok.getLocation(), "=");
+ }
Init = ParseInitializer();
- else if (Tok.is(tok::l_brace)) {
+ } else if (Tok.is(tok::l_brace)) {
BalancedDelimiterTracker Braces(*this, tok::l_brace);
Braces.consumeOpen();
Braces.skipToEnd();
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index b556f18b76..c6af2edee5 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -8702,6 +8702,14 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
CheckVariableDeclarationType(VDecl);
if (VDecl->isInvalidDecl())
return;
+
+ // If all looks well, warn if this is a case that will change meaning when
+ // we implement N3922.
+ if (DirectInit && !CXXDirectInit && isa<InitListExpr>(Init)) {
+ Diag(Init->getLocStart(),
+ diag::warn_auto_var_direct_list_init)
+ << FixItHint::CreateInsertion(Init->getLocStart(), "=");
+ }
}
// dllimport cannot be used on variable definitions.
diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp
index 6be200dd54..1228c74b07 100644
--- a/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp
+++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp
@@ -48,7 +48,7 @@ auto bad_init_2 = [a(1, 2)] {}; // expected-error {{initializer for lambda captu
auto bad_init_3 = [&a(void_fn())] {}; // expected-error {{cannot form a reference to 'void'}}
auto bad_init_4 = [a(void_fn())] {}; // expected-error {{has incomplete type 'void'}}
auto bad_init_5 = [a(overload_fn)] {}; // expected-error {{cannot deduce type for lambda capture 'a' from initializer of type '<overloaded function}}
-auto bad_init_6 = [a{overload_fn}] {}; // expected-error {{cannot deduce type for lambda capture 'a' from initializer list}}
+auto bad_init_6 = [a{overload_fn}] {}; // expected-error {{cannot deduce type for lambda capture 'a' from initializer list}} expected-warning {{will change meaning in a future version of Clang}}
template<typename...T> void pack_1(T...t) { (void)[a(t...)] {}; } // expected-error {{initializer missing for lambda capture 'a'}}
template void pack_1<>(); // expected-note {{instantiation of}}
@@ -61,7 +61,7 @@ auto a = [a(4), b = 5, &c = static_cast<const int&&>(0)] {
using T = decltype(c);
using T = const int &;
};
-auto b = [a{0}] {}; // expected-error {{include <initializer_list>}}
+auto b = [a{0}] {}; // expected-error {{include <initializer_list>}} expected-warning {{will change meaning in a future version of Clang}}
struct S { S(); S(S&&); };
template<typename T> struct remove_reference { typedef T type; };
diff --git a/test/Parser/cxx0x-lambda-expressions.cpp b/test/Parser/cxx0x-lambda-expressions.cpp
index 6f69d8096e..c2bf6fd396 100644
--- a/test/Parser/cxx0x-lambda-expressions.cpp
+++ b/test/Parser/cxx0x-lambda-expressions.cpp
@@ -61,7 +61,7 @@ class C {
int z;
void init_capture() {
[n(0)] () mutable -> int { return ++n; }; // expected-warning{{extension}}
- [n{0}] { return; }; // expected-error {{<initializer_list>}} expected-warning{{extension}}
+ [n{0}] { return; }; // expected-error {{<initializer_list>}} expected-warning{{extension}} expected-warning{{will change meaning in a future version}}
[n = 0] { return ++n; }; // expected-error {{captured by copy in a non-mutable}} expected-warning{{extension}}
[n = {0}] { return; }; // expected-error {{<initializer_list>}} expected-warning{{extension}}
[a([&b = z]{})](){}; // expected-warning 2{{extension}}
diff --git a/test/Parser/objcxx0x-lambda-expressions.mm b/test/Parser/objcxx0x-lambda-expressions.mm
index bef576a9d2..3954a807a5 100644
--- a/test/Parser/objcxx0x-lambda-expressions.mm
+++ b/test/Parser/objcxx0x-lambda-expressions.mm
@@ -21,7 +21,7 @@ class C {
[foo(bar)] () {};
[foo = bar] () {};
- [foo{bar}] () {}; // expected-error {{<initializer_list>}}
+ [foo{bar}] () {}; // expected-error {{<initializer_list>}} expected-warning {{will change meaning}}
[foo = {bar}] () {}; // expected-error {{<initializer_list>}}
[foo(bar) baz] () {}; // expected-error {{called object type 'int' is not a function}}
diff --git a/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp b/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
index 70f7c642a5..2405d2afe3 100644
--- a/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
+++ b/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
@@ -117,6 +117,7 @@ void argument_deduction() {
void auto_deduction() {
auto l = {1, 2, 3, 4};
+ auto l2 {1, 2, 3, 4}; // expected-warning {{will change meaning in a future version of Clang}}
static_assert(same_type<decltype(l), std::initializer_list<int>>::value, "");
auto bl = {1, 2.0}; // expected-error {{cannot deduce}}