From f06a0c83eb2f36bf182224a127ad378f42ab5094 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Wed, 11 Feb 2015 03:32:18 +0000 Subject: 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 --- include/clang/Basic/DiagnosticGroups.td | 3 +++ include/clang/Basic/DiagnosticParseKinds.td | 4 ++++ include/clang/Basic/DiagnosticSemaKinds.td | 4 ++++ lib/Parse/ParseExprCXX.cpp | 11 ++++++++--- lib/Sema/SemaDecl.cpp | 8 ++++++++ test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp | 4 ++-- test/Parser/cxx0x-lambda-expressions.cpp | 2 +- test/Parser/objcxx0x-lambda-expressions.mm | 2 +- test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp | 1 + 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; // 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; 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 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(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 ' 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(0)] { using T = decltype(c); using T = const int &; }; -auto b = [a{0}] {}; // expected-error {{include }} +auto b = [a{0}] {}; // expected-error {{include }} expected-warning {{will change meaning in a future version of Clang}} struct S { S(); S(S&&); }; template 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 {{}} expected-warning{{extension}} + [n{0}] { return; }; // expected-error {{}} 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 {{}} 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 {{}} + [foo{bar}] () {}; // expected-error {{}} expected-warning {{will change meaning}} [foo = {bar}] () {}; // expected-error {{}} [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>::value, ""); auto bl = {1, 2.0}; // expected-error {{cannot deduce}} -- cgit v1.2.3