llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang-codegen @llvm/pr-subscribers-clang Author: Aaron Ballman (AaronBallman) <details> <summary>Changes</summary> WG14 N3274 removed _Imaginary from Annex G. Clang has never fully supported Annex G or _Imaginary, so removal is pretty trivial for us. Note, we are keeping _Imaginary as a keyword so that we get better diagnostic behavior. This is still conforming because _I makes it a reserved identifier, so it's not available for users to use as an identifier anyway. --- Full diff: https://github.com/llvm/llvm-project/pull/97436.diff 10 Files Affected: - (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (-1) - (modified) clang/include/clang/Basic/TokenKinds.def (+5) - (modified) clang/include/clang/Sema/DeclSpec.h (+2-2) - (modified) clang/lib/CodeGen/CGExprComplex.cpp (-5) - (modified) clang/lib/Sema/DeclSpec.cpp (+3-3) - (modified) clang/lib/Sema/SemaCodeComplete.cpp (+2-1) - (modified) clang/lib/Sema/SemaLookup.cpp (+4-1) - (modified) clang/lib/Sema/SemaType.cpp (+3-1) - (added) clang/test/C/C2y/n3274.c (+18) - (modified) clang/www/c_status.html (+1-1) ``````````diff diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 3df64b2ecef1b..39655bd4f9ef4 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -7696,7 +7696,6 @@ def err_qualified_objc_access : Error< def ext_freestanding_complex : Extension< "complex numbers are an extension in a freestanding C99 implementation">; -// FIXME: Remove when we support imaginary. def err_imaginary_not_supported : Error<"imaginary types are not supported">; // Obj-c expressions diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index 37d570ca5e75b..e605442590909 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -331,6 +331,11 @@ KEYWORD(_Atomic , KEYALL|KEYNOOPENCL) KEYWORD(_Bool , KEYNOCXX) KEYWORD(_Complex , KEYALL) KEYWORD(_Generic , KEYALL) +// Note, C2y removed support for _Imaginary; we retain it as a keyword because +// 1) it's a reserved identifier, so we're allowed to steal it, 2) there's no +// good way to specify a keyword in earlier but not later language modes within +// this file, 3) this allows us to provide a better diagnostic in case a user +// does use the keyword. KEYWORD(_Imaginary , KEYALL) KEYWORD(_Noreturn , KEYALL) KEYWORD(_Static_assert , KEYALL) diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index 23bc780e04979..425b6e2a0b30c 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -269,7 +269,7 @@ class DeclSpec { enum TSC { TSC_unspecified, - TSC_imaginary, + TSC_imaginary, // Unsupported TSC_complex }; @@ -875,7 +875,7 @@ class DeclSpec { } /// Finish - This does final analysis of the declspec, issuing diagnostics for - /// things like "_Imaginary" (lacking an FP type). After calling this method, + /// things like "_Complex" (lacking an FP type). After calling this method, /// DeclSpec is guaranteed self-consistent, even if an error occurred. void Finish(Sema &S, const PrintingPolicy &Policy); diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp index 84ad3b566b647..000d4ff5c0698 100644 --- a/clang/lib/CodeGen/CGExprComplex.cpp +++ b/clang/lib/CodeGen/CGExprComplex.cpp @@ -817,8 +817,6 @@ ComplexPairTy ComplexExprEmitter::EmitBinMul(const BinOpInfo &Op) { // // But we can fold away components which would be zero due to a real // operand according to C11 Annex G.5.1p2. - // FIXME: C11 also provides for imaginary types which would allow folding - // still more of this within the type system. CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, Op.FPFeatures); if (Op.LHS.second && Op.RHS.second) { @@ -1049,9 +1047,6 @@ ComplexPairTy ComplexExprEmitter::EmitBinDiv(const BinOpInfo &Op) { // delegate to a libcall to handle all of the complexities and minimize // underflow/overflow cases. When FastMath is allowed we construct the // divide inline using the same algorithm as for integer operands. - // - // FIXME: We would be able to avoid the libcall in many places if we - // supported imaginary types in addition to complex types. BinOpInfo LibCallOp = Op; // If LHS was a real, supply a null imaginary part. if (!LHSi) diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index 96c90a60b9682..9a4d52d4b6b71 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -1146,7 +1146,7 @@ void DeclSpec::SaveWrittenBuiltinSpecs() { } /// Finish - This does final analysis of the declspec, rejecting things like -/// "_Imaginary" (lacking an FP type). After calling this method, DeclSpec is +/// "_Complex" (lacking an FP type). After calling this method, DeclSpec is /// guaranteed to be self-consistent, even if an error occurred. void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) { // Before possibly changing their values, save specs as written. @@ -1331,8 +1331,8 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) { break; } - // TODO: if the implementation does not implement _Complex or _Imaginary, - // disallow their use. Need information about the backend. + // TODO: if the implementation does not implement _Complex, disallow their + // use. Need information about the backend. if (TypeSpecComplex != TSC_unspecified) { if (TypeSpecType == TST_unspecified) { S.Diag(TSCLoc, diag::ext_plain_complex) diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index cd1c5f9391ccd..0e4e466aca678 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -1805,7 +1805,8 @@ static void AddTypeSpecifierResults(const LangOptions &LangOpts, if (LangOpts.C99) { // C99-specific Results.AddResult(Result("_Complex", CCP_Type)); - Results.AddResult(Result("_Imaginary", CCP_Type)); + if (!LangOpts.C2y) + Results.AddResult(Result("_Imaginary", CCP_Type)); Results.AddResult(Result("_Bool", CCP_Type)); Results.AddResult(Result("restrict", CCP_Type)); } diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index a4acf3b4fbf41..7851c5d080cf3 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -4983,7 +4983,7 @@ static void AddKeywordsToConsumer(Sema &SemaRef, static const char *const CTypeSpecs[] = { "char", "const", "double", "enum", "float", "int", "long", "short", "signed", "struct", "union", "unsigned", "void", "volatile", - "_Complex", "_Imaginary", + "_Complex", // storage-specifiers as well "extern", "inline", "static", "typedef" }; @@ -4991,6 +4991,9 @@ static void AddKeywordsToConsumer(Sema &SemaRef, for (const auto *CTS : CTypeSpecs) Consumer.addKeywordResult(CTS); + if (SemaRef.getLangOpts().C99 && !SemaRef.getLangOpts().C2y) + Consumer.addKeywordResult("_Imaginary"); + if (SemaRef.getLangOpts().C99) Consumer.addKeywordResult("restrict"); if (SemaRef.getLangOpts().Bool || SemaRef.getLangOpts().CPlusPlus) diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 50c15a1aa89e8..b9a975fb3073f 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -1423,7 +1423,9 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { Result = Context.getVectorType(Result, 128/typeSize, VecKind); } - // FIXME: Imaginary. + // _Imaginary was a feature of C99 through C23 but was never supported in + // Clang. The feature was removed in C2y, but we retain the unsupported + // diagnostic for an improved user experience. if (DS.getTypeSpecComplex() == DeclSpec::TSC_imaginary) S.Diag(DS.getTypeSpecComplexLoc(), diag::err_imaginary_not_supported); diff --git a/clang/test/C/C2y/n3274.c b/clang/test/C/C2y/n3274.c new file mode 100644 index 0000000000000..ccdb89f4069de --- /dev/null +++ b/clang/test/C/C2y/n3274.c @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -verify -std=c23 -Wall -pedantic %s +// RUN: %clang_cc1 -verify -std=c2y -Wall -pedantic %s + +/* WG14 N3274: Yes + * Remove imaginary types + */ + +// Clang has never supported _Imaginary. +#ifdef __STDC_IEC_559_COMPLEX__ +#error "When did this happen?" +#endif + +_Imaginary float i; // expected-error {{imaginary types are not supported}} + +// _Imaginary is a keyword in older language modes, but doesn't need to be one +// in C2y or later. However, to improve diagnostic behavior, we retain it as a +// keyword in all language modes -- it is not available as an identifier. +static_assert(!__is_identifier(_Imaginary)); diff --git a/clang/www/c_status.html b/clang/www/c_status.html index ccb39a15b25aa..cf2edb317b4a6 100644 --- a/clang/www/c_status.html +++ b/clang/www/c_status.html @@ -1292,7 +1292,7 @@ <h2 id="c2y">C2y implementation status</h2> <tr> <td>Remove imaginary types</td> <td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3274.pdf">N3274</a></td> - <td class="unknown" align="center">Unknown</td> + <td class="full" align="center">Yes</td> </tr> </table> </details> `````````` </details> https://github.com/llvm/llvm-project/pull/97436 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits