Skip to content

Commit c22625c

Browse files
authored
[C2y] Remove support for _Imaginary (#97436)
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.
1 parent 03d4332 commit c22625c

File tree

10 files changed

+38
-15
lines changed

10 files changed

+38
-15
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7696,7 +7696,6 @@ def err_qualified_objc_access : Error<
76967696
def ext_freestanding_complex : Extension<
76977697
"complex numbers are an extension in a freestanding C99 implementation">;
76987698

7699-
// FIXME: Remove when we support imaginary.
77007699
def err_imaginary_not_supported : Error<"imaginary types are not supported">;
77017700

77027701
// Obj-c expressions

clang/include/clang/Basic/TokenKinds.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,11 @@ KEYWORD(_Atomic , KEYALL|KEYNOOPENCL)
331331
KEYWORD(_Bool , KEYNOCXX)
332332
KEYWORD(_Complex , KEYALL)
333333
KEYWORD(_Generic , KEYALL)
334+
// Note, C2y removed support for _Imaginary; we retain it as a keyword because
335+
// 1) it's a reserved identifier, so we're allowed to steal it, 2) there's no
336+
// good way to specify a keyword in earlier but not later language modes within
337+
// this file, 3) this allows us to provide a better diagnostic in case a user
338+
// does use the keyword.
334339
KEYWORD(_Imaginary , KEYALL)
335340
KEYWORD(_Noreturn , KEYALL)
336341
KEYWORD(_Static_assert , KEYALL)

clang/include/clang/Sema/DeclSpec.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ class DeclSpec {
269269

270270
enum TSC {
271271
TSC_unspecified,
272-
TSC_imaginary,
272+
TSC_imaginary, // Unsupported
273273
TSC_complex
274274
};
275275

@@ -875,7 +875,7 @@ class DeclSpec {
875875
}
876876

877877
/// Finish - This does final analysis of the declspec, issuing diagnostics for
878-
/// things like "_Imaginary" (lacking an FP type). After calling this method,
878+
/// things like "_Complex" (lacking an FP type). After calling this method,
879879
/// DeclSpec is guaranteed self-consistent, even if an error occurred.
880880
void Finish(Sema &S, const PrintingPolicy &Policy);
881881

clang/lib/CodeGen/CGExprComplex.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -817,8 +817,6 @@ ComplexPairTy ComplexExprEmitter::EmitBinMul(const BinOpInfo &Op) {
817817
//
818818
// But we can fold away components which would be zero due to a real
819819
// operand according to C11 Annex G.5.1p2.
820-
// FIXME: C11 also provides for imaginary types which would allow folding
821-
// still more of this within the type system.
822820

823821
CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, Op.FPFeatures);
824822
if (Op.LHS.second && Op.RHS.second) {
@@ -1049,9 +1047,6 @@ ComplexPairTy ComplexExprEmitter::EmitBinDiv(const BinOpInfo &Op) {
10491047
// delegate to a libcall to handle all of the complexities and minimize
10501048
// underflow/overflow cases. When FastMath is allowed we construct the
10511049
// divide inline using the same algorithm as for integer operands.
1052-
//
1053-
// FIXME: We would be able to avoid the libcall in many places if we
1054-
// supported imaginary types in addition to complex types.
10551050
BinOpInfo LibCallOp = Op;
10561051
// If LHS was a real, supply a null imaginary part.
10571052
if (!LHSi)

clang/lib/Sema/DeclSpec.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1146,7 +1146,7 @@ void DeclSpec::SaveWrittenBuiltinSpecs() {
11461146
}
11471147

11481148
/// Finish - This does final analysis of the declspec, rejecting things like
1149-
/// "_Imaginary" (lacking an FP type). After calling this method, DeclSpec is
1149+
/// "_Complex" (lacking an FP type). After calling this method, DeclSpec is
11501150
/// guaranteed to be self-consistent, even if an error occurred.
11511151
void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
11521152
// Before possibly changing their values, save specs as written.
@@ -1331,8 +1331,8 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
13311331
break;
13321332
}
13331333

1334-
// TODO: if the implementation does not implement _Complex or _Imaginary,
1335-
// disallow their use. Need information about the backend.
1334+
// TODO: if the implementation does not implement _Complex, disallow their
1335+
// use. Need information about the backend.
13361336
if (TypeSpecComplex != TSC_unspecified) {
13371337
if (TypeSpecType == TST_unspecified) {
13381338
S.Diag(TSCLoc, diag::ext_plain_complex)

clang/lib/Sema/SemaCodeComplete.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1805,7 +1805,8 @@ static void AddTypeSpecifierResults(const LangOptions &LangOpts,
18051805
if (LangOpts.C99) {
18061806
// C99-specific
18071807
Results.AddResult(Result("_Complex", CCP_Type));
1808-
Results.AddResult(Result("_Imaginary", CCP_Type));
1808+
if (!LangOpts.C2y)
1809+
Results.AddResult(Result("_Imaginary", CCP_Type));
18091810
Results.AddResult(Result("_Bool", CCP_Type));
18101811
Results.AddResult(Result("restrict", CCP_Type));
18111812
}

clang/lib/Sema/SemaLookup.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4983,14 +4983,17 @@ static void AddKeywordsToConsumer(Sema &SemaRef,
49834983
static const char *const CTypeSpecs[] = {
49844984
"char", "const", "double", "enum", "float", "int", "long", "short",
49854985
"signed", "struct", "union", "unsigned", "void", "volatile",
4986-
"_Complex", "_Imaginary",
4986+
"_Complex",
49874987
// storage-specifiers as well
49884988
"extern", "inline", "static", "typedef"
49894989
};
49904990

49914991
for (const auto *CTS : CTypeSpecs)
49924992
Consumer.addKeywordResult(CTS);
49934993

4994+
if (SemaRef.getLangOpts().C99 && !SemaRef.getLangOpts().C2y)
4995+
Consumer.addKeywordResult("_Imaginary");
4996+
49944997
if (SemaRef.getLangOpts().C99)
49954998
Consumer.addKeywordResult("restrict");
49964999
if (SemaRef.getLangOpts().Bool || SemaRef.getLangOpts().CPlusPlus)

clang/lib/Sema/SemaType.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1423,7 +1423,9 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
14231423
Result = Context.getVectorType(Result, 128/typeSize, VecKind);
14241424
}
14251425

1426-
// FIXME: Imaginary.
1426+
// _Imaginary was a feature of C99 through C23 but was never supported in
1427+
// Clang. The feature was removed in C2y, but we retain the unsupported
1428+
// diagnostic for an improved user experience.
14271429
if (DS.getTypeSpecComplex() == DeclSpec::TSC_imaginary)
14281430
S.Diag(DS.getTypeSpecComplexLoc(), diag::err_imaginary_not_supported);
14291431

clang/test/C/C2y/n3274.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// RUN: %clang_cc1 -verify -std=c23 -Wall -pedantic %s
2+
// RUN: %clang_cc1 -verify -std=c2y -Wall -pedantic %s
3+
4+
/* WG14 N3274: Yes
5+
* Remove imaginary types
6+
*/
7+
8+
// Clang has never supported _Imaginary.
9+
#ifdef __STDC_IEC_559_COMPLEX__
10+
#error "When did this happen?"
11+
#endif
12+
13+
_Imaginary float i; // expected-error {{imaginary types are not supported}}
14+
15+
// _Imaginary is a keyword in older language modes, but doesn't need to be one
16+
// in C2y or later. However, to improve diagnostic behavior, we retain it as a
17+
// keyword in all language modes -- it is not available as an identifier.
18+
static_assert(!__is_identifier(_Imaginary));

clang/www/c_status.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1292,7 +1292,7 @@ <h2 id="c2y">C2y implementation status</h2>
12921292
<tr>
12931293
<td>Remove imaginary types</td>
12941294
<td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3274.pdf">N3274</a></td>
1295-
<td class="unknown" align="center">Unknown</td>
1295+
<td class="full" align="center">Yes</td>
12961296
</tr>
12971297
</table>
12981298
</details>

0 commit comments

Comments
 (0)