-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[C2y] Add test coverage and documentation for WG14 N3342 #115494
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This paper made qualified function types implementation-defined. We have always supported this as an extension, so now we're documenting our behavior. Note, we still warn about this by default even in C2y mode because a qualified function type is a sign of programmer confusion.
@llvm/pr-subscribers-clang Author: Aaron Ballman (AaronBallman) ChangesThis paper made qualified function types implementation-defined. We have always supported this as an extension, so now we're documenting our behavior. Note, we still warn about this by default even in C2y mode because a qualified function type is a sign of programmer confusion. Full diff: https://github.com/llvm/llvm-project/pull/115494.diff 8 Files Affected:
diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst
index f7285352b9deb9..a051eb95898ecf 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -5974,3 +5974,20 @@ Clang guarantees the following behaviors:
padding bits are initialized to zero.
Currently, the above extension only applies to C source code, not C++.
+
+Qualified function types in C
+=============================
+Declaring a function with a qualified type in C is undefined behavior (C23 and
+earlier) or implementation-defined behavior (C2y). Clang allows a function type
+to be specified with the ``const`` and ``volatile`` qualifiers, but ignores the
+qualifications.
+
+.. code-block:: c
+
+ typedef int f(void);
+ const volatile f func; // Qualifier on function type has no effect.
+
+
+Note, Clang does not allow an ``_Atomic`` function type because
+of explicit constraints against atomically qualified (arrays and) function
+types.
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index d0c43ff11f7bae..d4bf05651a63eb 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -298,6 +298,11 @@ C2y Feature Support
paper adopts Clang's existing practice, so there were no changes to compiler
behavior.
+- Updated conformance for `N3342 <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3342.pdf>`_
+ which made qualified function types implementation-defined rather than
+ undefined. Clang has always accepted ``const`` and ``volatile`` qualified
+ function types by ignoring the qualifiers.
+
C23 Feature Support
^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 6a244c276facd6..ae95ea6d558cb0 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6241,8 +6241,9 @@ def err_typecheck_negative_array_size : Error<"array size is negative">;
def warn_typecheck_function_qualifiers_ignored : Warning<
"'%0' qualifier on function type %1 has no effect">,
InGroup<IgnoredQualifiers>;
-def warn_typecheck_function_qualifiers_unspecified : Warning<
- "'%0' qualifier on function type %1 has unspecified behavior">;
+def ext_typecheck_function_qualifiers_unspecified : ExtWarn<
+ "'%0' qualifier on function type %1 has no effect and is a Clang extension">,
+ InGroup<IgnoredQualifiers>;
def warn_typecheck_reference_qualifiers : Warning<
"'%0' qualifier on reference type %1 has no effect">,
InGroup<IgnoredReferenceQualifiers>;
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index e526a11973975d..515b9f689a248a 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -1500,16 +1500,19 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
// C99 6.7.3p8:
// If the specification of a function type includes any type qualifiers,
// the behavior is undefined.
+ // C2y changed this behavior to be implementation-defined. Clang defines
+ // the behavior in all cases to ignore the qualifier, as in C++.
// C++11 [dcl.fct]p7:
// The effect of a cv-qualifier-seq in a function declarator is not the
// same as adding cv-qualification on top of the function type. In the
// latter case, the cv-qualifiers are ignored.
if (Result->isFunctionType()) {
+ unsigned DiagId = diag::warn_typecheck_function_qualifiers_ignored;
+ if (!S.getLangOpts().CPlusPlus && !S.getLangOpts().C2y)
+ DiagId = diag::ext_typecheck_function_qualifiers_unspecified;
diagnoseAndRemoveTypeQualifiers(
S, DS, TypeQuals, Result, DeclSpec::TQ_const | DeclSpec::TQ_volatile,
- S.getLangOpts().CPlusPlus
- ? diag::warn_typecheck_function_qualifiers_ignored
- : diag::warn_typecheck_function_qualifiers_unspecified);
+ DiagId);
// No diagnostic for 'restrict' or '_Atomic' applied to a
// function type; we'll diagnose those later, in BuildQualifiedType.
}
diff --git a/clang/test/C/C2y/n3342.c b/clang/test/C/C2y/n3342.c
new file mode 100644
index 00000000000000..3c5282c7831f32
--- /dev/null
+++ b/clang/test/C/C2y/n3342.c
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -verify=expected,both -std=c2y -Wall -pedantic %s
+// RUN: %clang_cc1 -verify=clang,both -Wall -pedantic %s
+
+/* WG14 N3342: Yes
+ * Slay Some Earthly Demons IV
+ *
+ * Qualified function types are now implementation-defined instead of
+ * undefined. Clang strips the qualifiers.
+ */
+
+typedef int f(void);
+
+const f one; /* expected-warning {{'const' qualifier on function type 'f' (aka 'int (void)') has no effect}}
+ clang-warning {{'const' qualifier on function type 'f' (aka 'int (void)') has no effect and is a Clang extension}}
+ */
+volatile f two; /* expected-warning {{'volatile' qualifier on function type 'f' (aka 'int (void)') has no effect}}
+ clang-warning {{'volatile' qualifier on function type 'f' (aka 'int (void)') has no effect and is a Clang extension}}
+ */
+
+const volatile f three; /* expected-warning {{'const' qualifier on function type 'f' (aka 'int (void)') has no effect}}
+ clang-warning {{'const' qualifier on function type 'f' (aka 'int (void)') has no effect and is a Clang extension}}
+ expected-warning {{'volatile' qualifier on function type 'f' (aka 'int (void)') has no effect}}
+ clang-warning {{'volatile' qualifier on function type 'f' (aka 'int (void)') has no effect and is a Clang extension}}
+ */
+
+// Atomic types have an explicit constraint making it ill-formed.
+_Atomic f four; // both-error {{_Atomic cannot be applied to function type 'f' (aka 'int (void)')}}
+
+// There's no point to testing 'restrict' because that requires a pointer type.
diff --git a/clang/test/Misc/warning-flags.c b/clang/test/Misc/warning-flags.c
index 80c01099140f79..1fd02440833359 100644
--- a/clang/test/Misc/warning-flags.c
+++ b/clang/test/Misc/warning-flags.c
@@ -18,7 +18,7 @@ This test serves two purposes:
The list of warnings below should NEVER grow. It should gradually shrink to 0.
-CHECK: Warnings without flags (62):
+CHECK: Warnings without flags (61):
CHECK-NEXT: ext_expected_semi_decl_list
CHECK-NEXT: ext_missing_whitespace_after_macro_name
@@ -76,7 +76,6 @@ CHECK-NEXT: warn_register_objc_catch_parm
CHECK-NEXT: warn_related_result_type_compatibility_class
CHECK-NEXT: warn_related_result_type_compatibility_protocol
CHECK-NEXT: warn_template_export_unsupported
-CHECK-NEXT: warn_typecheck_function_qualifiers
CHECK-NEXT: warn_undef_interface
CHECK-NEXT: warn_undef_interface_suggest
CHECK-NEXT: warn_undef_protocolref
diff --git a/clang/test/Sema/declspec.c b/clang/test/Sema/declspec.c
index 88ff83a2149067..ca3216bd2fafc4 100644
--- a/clang/test/Sema/declspec.c
+++ b/clang/test/Sema/declspec.c
@@ -16,9 +16,9 @@ int gv2;
static void buggy(int *x) { }
// Type qualifiers.
-typedef int f(void);
+typedef int f(void);
typedef f* fptr;
-const f* v1; // expected-warning {{qualifier on function type 'f' (aka 'int (void)') has unspecified behavior}}
+const f* v1; // expected-warning {{'const' qualifier on function type 'f' (aka 'int (void)') has no effect and is a Clang extension}}
__restrict__ f* v2; // expected-error {{restrict requires a pointer or reference ('f' (aka 'int (void)') is invalid)}}
__restrict__ fptr v3; // expected-error {{pointer to function type 'f' (aka 'int (void)') may not be 'restrict' qualified}}
f *__restrict__ v4; // expected-error {{pointer to function type 'f' (aka 'int (void)') may not be 'restrict' qualified}}
diff --git a/clang/www/c_status.html b/clang/www/c_status.html
index 989a572ae70fb6..fa2411e674d768 100644
--- a/clang/www/c_status.html
+++ b/clang/www/c_status.html
@@ -196,7 +196,7 @@ <h2 id="c2y">C2y implementation status</h2>
<tr>
<td>Slay Some Earthly Demons IV</td>
<td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3342.pdf">N3342</a></td>
- <td class="unknown" align="center">Unknown</td>
+ <td class="full" align="center">Yes</td>
</tr>
<tr>
<td>Slay Some Earthly Demons VI</td>
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/144/builds/11191 Here is the relevant piece of the build log for the reference
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/27/builds/1746 Here is the relevant piece of the build log for the reference
|
This paper made qualified function types implementation-defined. We have always supported this as an extension, so now we're documenting our behavior. Note, we still warn about this by default even in C2y mode because a qualified function type is a sign of programmer confusion.
This paper made qualified function types implementation-defined. We have always supported this as an extension, so now we're documenting our behavior.
Note, we still warn about this by default even in C2y mode because a qualified function type is a sign of programmer confusion.