From patchwork Fri Dec 1 20:16:23 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 843715 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-468361-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="yM1Clf9M"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3ypQXp5vfXz9s84 for ; Sat, 2 Dec 2017 07:16:57 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:from:date:message-id:subject:to:cc:content-type; q=dns; s=default; b=M7MvQleRlqC+7h/SiwAmJEN9yhJYv/rjNg2J7eKE0qh a+SBgZOUaDeyFLuQMtBqV6pxRdEg1TTc0caQk7Jb5BCgTOge84ggCTS40dUjc17y e7+wsoKH9t8PIMHytUIHL3s/Xd6Tv9KWuS1zZHu1cRA/kzuh6pm3lwP2QKJh192c = DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:from:date:message-id:subject:to:cc:content-type; s=default; bh=KS2rTozF7e4ATh5kOaoKA+/brvk=; b=yM1Clf9MB/bH4k7yG 9I13pH02nVV5efzkMP3TxtyfIHX3kEwsoEuGkGsg38untHZVsjSY8ySVIACLkX37 qtRBXLAY5tr0vR0uSASvpZmrpvkicx5TsrOE+xYT5Jxa2CYMCAwwh3Snl6QoDNbT K+UcoRxZaSB2T0cfJw3D5T5fQY= Received: (qmail 2030 invoked by alias); 1 Dec 2017 20:16:49 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 2017 invoked by uid 89); 1 Dec 2017 20:16:48 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.2 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KB_WAM_FROM_NAME_SINGLEWORD, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.2 spammy=tt, deque, complained X-HELO: mail-io0-f171.google.com Received: from mail-io0-f171.google.com (HELO mail-io0-f171.google.com) (209.85.223.171) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 01 Dec 2017 20:16:46 +0000 Received: by mail-io0-f171.google.com with SMTP id s19so12559066ioa.1 for ; Fri, 01 Dec 2017 12:16:46 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:from:date:message-id:subject:to:cc; bh=BrClAoksfTIXqwhgtT2qfJDZLVYzmuTkwg4S0eE51Pk=; b=Ogdky5W9Qc5hHQoSmkREZnfBKEAXA6cI7g9XOU0oY5kKz2uEpDIEJFzEhXov5qO2e1 5ZDekrg6dZT//vRkYHcC74V8MW7CcwflFvHMKpS39njvW8Cjd0zRH+y6+OIA7izZSccO XiyDZsRxU91xRS3rBW8Lji2OYegvR/O3/rmMXk+sw3PdLJjZKibVn4W9dVqGBEo5KFdP G7xwtv5H28aFuDnlOZhriUOm3qJmQdsv9Jx8UMjvVhodOHwYYQ3aGAm0lmhQ6e0yzKeI XxeoBtWYAPDxKLvLQS2816ul/Yd1mgJZxRCe9cnBMIKIQYL7lDvDYVAqreik+q2+wEBq QYVQ== X-Gm-Message-State: AJaThX6rLempbHl9H262LQZfzabwoe+iP+0LBIf6/xSTwPX9w8uunU/e U2vjEBR70Djjctgc774U2L4R9DnZkKppTeidH0ntDAVx X-Google-Smtp-Source: AGs4zMYq6EhgOdy6pAErJxFktzbXmo3CFHIF//+u4lfGqhX0FQPpMyvcFZy4Euy9L187BsmhPAXBxj7HCP74Us8D/Gc= X-Received: by 10.107.32.18 with SMTP id g18mr13792927iog.227.1512159404236; Fri, 01 Dec 2017 12:16:44 -0800 (PST) MIME-Version: 1.0 Received: by 10.107.171.134 with HTTP; Fri, 1 Dec 2017 12:16:23 -0800 (PST) From: Jason Merrill Date: Fri, 1 Dec 2017 15:16:23 -0500 Message-ID: Subject: C++ PATCH for c++/79228, complex literal suffixes To: gcc-patches List Cc: David Malcolm X-IsSubscribed: yes 79228 points out that C++14 defines complex literal suffixes that conflict with the GNU suffixes. In this patch I take the approach that in C++14 and up, if has been included we assume that the user wants the C++14 suffixes and give a hard error if they aren't found; otherwise we assume that the user wants the GNU suffixes and give a pedwarn if -Wpedantic. While looking at this, I noticed that David's #include suggestion code wasn't suggesting for references to std::complex, so the second patch addresses that. Tested x86_64-pc-linux-gnu, applying to trunk. commit e39b7d506d236ce7ef9f64d1bcf0b384bb2d8038 Author: Jason Merrill Date: Fri Dec 1 07:45:03 2017 -0500 PR c++/79228 - extensions hide C++14 complex literal operators libcpp/ * expr.c (interpret_float_suffix): Ignore 'i' in C++14 and up. (interpret_int_suffix): Likewise. gcc/cp/ * parser.c (cp_parser_userdef_numeric_literal): Be helpful about 'i' in C++14 and up. commit 59576ea299c27f6b3f29eb5e6171949a72720dbe Author: Jason Merrill Date: Fri Dec 1 13:22:40 2017 -0500 Give #include hints for . * name-lookup.c (get_std_name_hint): Add . * parser.c (cp_parser_diagnose_invalid_type_name): Call suggest_alternative_in_explicit_scope. (cp_parser_namespace_name): Likewise. diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 9f65c4d7992..62ea564cedd 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -5414,6 +5414,9 @@ get_std_name_hint (const char *name) static const std_name_hint hints[] = { /* . */ {"array", ""}, // C++11 + /* . */ + {"complex", ""}, + {"complex_literals", ""}, /* . */ {"deque", ""}, /* . */ diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 6e4c24362c6..891f742eb21 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -3365,6 +3365,9 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id, id, parser->scope); if (DECL_P (decl)) inform (DECL_SOURCE_LOCATION (decl), "%qD declared here", decl); + else if (decl == error_mark_node) + suggest_alternative_in_explicit_scope (location, id, + parser->scope); } else if (CLASS_TYPE_P (parser->scope) && constructor_name_p (id, parser->scope)) @@ -18408,7 +18411,13 @@ cp_parser_namespace_name (cp_parser* parser) || TREE_CODE (namespace_decl) != NAMESPACE_DECL) { if (!cp_parser_uncommitted_to_tentative_parse_p (parser)) - error_at (token->location, "%qD is not a namespace-name", identifier); + { + error_at (token->location, "%qD is not a namespace-name", identifier); + if (namespace_decl == error_mark_node + && parser->scope && TREE_CODE (parser->scope) == NAMESPACE_DECL) + suggest_alternative_in_explicit_scope (token->location, identifier, + parser->scope); + } cp_parser_error (parser, "expected namespace-name"); namespace_decl = error_mark_node; } diff --git a/gcc/testsuite/g++.dg/lookup/missing-std-include-4.C b/gcc/testsuite/g++.dg/lookup/missing-std-include-4.C new file mode 100644 index 00000000000..abf4e96bd3e --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/missing-std-include-4.C @@ -0,0 +1,2 @@ +std::complex c; // { dg-error "" } +// { dg-message "#include " "" { target *-*-* } .-1 } diff --git a/gcc/testsuite/g++.dg/lookup/missing-std-include-5.C b/gcc/testsuite/g++.dg/lookup/missing-std-include-5.C new file mode 100644 index 00000000000..fe880a6263b --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/missing-std-include-5.C @@ -0,0 +1,2 @@ +using namespace std::complex_literals; // { dg-error "" } +// { dg-message "#include " "" { target *-*-* } .-1 } diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index b469d1c1760..6e4c24362c6 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -4397,11 +4397,75 @@ cp_parser_userdef_numeric_literal (cp_parser *parser) release_tree_vector (args); - error ("unable to find numeric literal operator %qD", name); - if (!cpp_get_options (parse_in)->ext_numeric_literals) - inform (token->location, "use -std=gnu++11 or -fext-numeric-literals " + /* In C++14 the standard library defines complex number suffixes that + conflict with GNU extensions. Prefer them if is #included. */ + bool ext = cpp_get_options (parse_in)->ext_numeric_literals; + bool i14 = (cxx_dialect > cxx11 + && (id_equal (suffix_id, "i") + || id_equal (suffix_id, "if") + || id_equal (suffix_id, "il"))); + diagnostic_t kind = DK_ERROR; + int opt = 0; + + if (i14 && ext) + { + tree cxlit = lookup_qualified_name (std_node, + get_identifier ("complex_literals"), + 0, false, false); + if (cxlit == error_mark_node) + { + /* No , so pedwarn and use GNU semantics. */ + kind = DK_PEDWARN; + opt = OPT_Wpedantic; + } + } + + bool complained + = emit_diagnostic (kind, input_location, opt, + "unable to find numeric literal operator %qD", name); + + if (!complained) + /* Don't inform either. */; + else if (i14) + { + inform (token->location, "add % " + "(from ) to enable the C++14 user-defined literal " + "suffixes"); + if (ext) + inform (token->location, "or use % instead of % for the " + "GNU built-in suffix"); + } + else if (!ext) + inform (token->location, "use -fext-numeric-literals " "to enable more built-in suffixes"); - return error_mark_node; + + if (kind == DK_ERROR) + value = error_mark_node; + else + { + /* Use the built-in semantics. */ + tree type; + if (id_equal (suffix_id, "i")) + { + if (TREE_CODE (value) == INTEGER_CST) + type = integer_type_node; + else + type = double_type_node; + } + else if (id_equal (suffix_id, "if")) + type = float_type_node; + else /* if (id_equal (suffix_id, "il")) */ + type = long_double_type_node; + + value = build_complex (build_complex_type (type), + fold_convert (type, integer_zero_node), + fold_convert (type, value)); + } + + if (cp_parser_uncommitted_to_tentative_parse_p (parser)) + /* Avoid repeated diagnostics. */ + token->u.value = value; + return value; } /* Parse a user-defined string constant. Returns a call to a user-defined diff --git a/gcc/testsuite/g++.dg/cpp0x/gnu_fext-numeric-literals.C b/gcc/testsuite/g++.dg/cpp0x/gnu_fext-numeric-literals.C index 6a8398b896a..ac2db287f3a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/gnu_fext-numeric-literals.C +++ b/gcc/testsuite/g++.dg/cpp0x/gnu_fext-numeric-literals.C @@ -4,7 +4,7 @@ // Integer imaginary... constexpr unsigned long long -operator"" i(unsigned long long n) // { dg-warning "shadowed by implementation" } +operator"" i(unsigned long long n) // { dg-warning "shadowed by implementation" "" { target c++11_only } } { return 4 * n + 0; } constexpr unsigned long long @@ -22,7 +22,7 @@ operator"" J(unsigned long long n) // { dg-warning "shadowed by implementation" // Floating-point imaginary... constexpr long double -operator"" i(long double n) // { dg-warning "shadowed by implementation" } +operator"" i(long double n) // { dg-warning "shadowed by implementation" "" { target c++11_only } } { return 4.0L * n + 0.0L; } constexpr long double diff --git a/gcc/testsuite/g++.dg/cpp0x/std_fext-numeric-literals.C b/gcc/testsuite/g++.dg/cpp0x/std_fext-numeric-literals.C index 7caaa7cee8d..ff1e7b6d966 100644 --- a/gcc/testsuite/g++.dg/cpp0x/std_fext-numeric-literals.C +++ b/gcc/testsuite/g++.dg/cpp0x/std_fext-numeric-literals.C @@ -4,7 +4,7 @@ // Integer imaginary... constexpr unsigned long long -operator"" i(unsigned long long n) // { dg-warning "shadowed by implementation" } +operator"" i(unsigned long long n) // { dg-warning "shadowed by implementation" "" { target c++11_only } } { return 4 * n + 0; } constexpr unsigned long long @@ -22,7 +22,7 @@ operator"" J(unsigned long long n) // { dg-warning "shadowed by implementation" // Floating-point imaginary... constexpr long double -operator"" i(long double n) // { dg-warning "shadowed by implementation" } +operator"" i(long double n) // { dg-warning "shadowed by implementation" "" { target c++11_only } } { return 4.0L * n + 0.0L; } constexpr long double diff --git a/gcc/testsuite/g++.dg/cpp1y/complex_literals1.C b/gcc/testsuite/g++.dg/cpp1y/complex_literals1.C new file mode 100644 index 00000000000..5ae2370c3ff --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/complex_literals1.C @@ -0,0 +1,10 @@ +// PR c++/79228 +// { dg-do compile { target c++14 } } + +#include + +int main() +{ + using namespace std::complex_literals; + auto a = std::abs(0.0i); +} diff --git a/gcc/testsuite/g++.dg/cpp1y/complex_literals1a.C b/gcc/testsuite/g++.dg/cpp1y/complex_literals1a.C new file mode 100644 index 00000000000..9b61f3aa534 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/complex_literals1a.C @@ -0,0 +1,11 @@ +// PR c++/79228 +// { dg-do compile { target c++14 } } +// { dg-options "" } + +#include + +int main() +{ + auto a = std::abs(0.0i); // { dg-error "literal operator" } + // { dg-message "complex_literals" "" { target *-*-* } .-1 } +} diff --git a/gcc/testsuite/g++.dg/cpp1y/complex_literals2.C b/gcc/testsuite/g++.dg/cpp1y/complex_literals2.C new file mode 100644 index 00000000000..6dd9947dab8 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/complex_literals2.C @@ -0,0 +1,25 @@ +// PR c++/79228 +// { dg-do compile { target c++14 } } +// { dg-options "-Wpedantic" } + +template struct same; +template struct same { }; + +int main() +{ + same{}; // { dg-warning "literal operator" } + // { dg-message "complex_literals" "" { target *-*-* } .-1 } + // { dg-message "built-in" "" { target *-*-* } .-2 } + + same{}; // { dg-warning "literal operator" } + // { dg-message "complex_literals" "" { target *-*-* } .-1 } + // { dg-message "built-in" "" { target *-*-* } .-2 } + + same{}; // { dg-warning "literal operator" } + // { dg-message "complex_literals" "" { target *-*-* } .-1 } + // { dg-message "built-in" "" { target *-*-* } .-2 } + + same{}; // { dg-warning "literal operator" } + // { dg-message "complex_literals" "" { target *-*-* } .-1 } + // { dg-message "built-in" "" { target *-*-* } .-2 } +} diff --git a/gcc/testsuite/g++.dg/cpp1y/complex_literals2a.C b/gcc/testsuite/g++.dg/cpp1y/complex_literals2a.C new file mode 100644 index 00000000000..9ee9f3fd24d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/complex_literals2a.C @@ -0,0 +1,14 @@ +// PR c++/79228 +// { dg-do compile { target c++14 } } +// { dg-options "" } + +template struct same; +template struct same { }; + +int main() +{ + same{}; + same{}; + same{}; + same{}; +} diff --git a/libcpp/expr.c b/libcpp/expr.c index 04675d8faee..fe9f6b0188c 100644 --- a/libcpp/expr.c +++ b/libcpp/expr.c @@ -90,6 +90,8 @@ static cpp_num parse_has_include (cpp_reader *, enum include_type); static unsigned int interpret_float_suffix (cpp_reader *pfile, const uchar *s, size_t len) { + size_t orig_len = len; + const uchar *orig_s = s; size_t flags; size_t f, d, l, w, q, i, fn, fnx, fn_bits; @@ -269,8 +271,20 @@ interpret_float_suffix (cpp_reader *pfile, const uchar *s, size_t len) if (fn && fn_bits == 96) return 0; - if (i && !CPP_OPTION (pfile, ext_numeric_literals)) - return 0; + if (i) + { + if (!CPP_OPTION (pfile, ext_numeric_literals)) + return 0; + + /* In C++14 and up these suffixes are in the standard library, so treat + them as user-defined literals. */ + if (CPP_OPTION (pfile, cplusplus) + && CPP_OPTION (pfile, lang) > CLK_CXX11 + && (!memcmp (orig_s, "i", orig_len) + || !memcmp (orig_s, "if", orig_len) + || !memcmp (orig_s, "il", orig_len))) + return 0; + } if ((w || q) && !CPP_OPTION (pfile, ext_numeric_literals)) return 0; @@ -299,6 +313,7 @@ cpp_interpret_float_suffix (cpp_reader *pfile, const char *s, size_t len) static unsigned int interpret_int_suffix (cpp_reader *pfile, const uchar *s, size_t len) { + size_t orig_len = len; size_t u, l, i; u = l = i = 0; @@ -321,8 +336,20 @@ interpret_int_suffix (cpp_reader *pfile, const uchar *s, size_t len) if (l > 2 || u > 1 || i > 1) return 0; - if (i && !CPP_OPTION (pfile, ext_numeric_literals)) - return 0; + if (i) + { + if (!CPP_OPTION (pfile, ext_numeric_literals)) + return 0; + + /* In C++14 and up these suffixes are in the standard library, so treat + them as user-defined literals. */ + if (CPP_OPTION (pfile, cplusplus) + && CPP_OPTION (pfile, lang) > CLK_CXX11 + && (!memcmp (s, "i", orig_len) + || !memcmp (s, "if", orig_len) + || !memcmp (s, "il", orig_len))) + return 0; + } return ((i ? CPP_N_IMAGINARY : 0) | (u ? CPP_N_UNSIGNED : 0)