Skip to content

Commit 95af947

Browse files
committed
Add %separated specifier
1 parent 07b326b commit 95af947

File tree

5 files changed

+62
-26
lines changed

5 files changed

+62
-26
lines changed

clang/include/clang/Basic/Diagnostic.h

+18-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "clang/Basic/DiagnosticOptions.h"
1919
#include "clang/Basic/SourceLocation.h"
2020
#include "clang/Basic/Specifiers.h"
21+
#include "llvm/ADT/APSInt.h"
2122
#include "llvm/ADT/ArrayRef.h"
2223
#include "llvm/ADT/DenseMap.h"
2324
#include "llvm/ADT/FunctionExtras.h"
@@ -284,7 +285,10 @@ class DiagnosticsEngine : public RefCountedBase<DiagnosticsEngine> {
284285
ak_qualtype_pair,
285286

286287
/// Attr *
287-
ak_attr
288+
ak_attr,
289+
290+
/// APSInt *
291+
ak_apsint,
288292
};
289293

290294
/// Represents on argument value, which is a union discriminated
@@ -1366,6 +1370,12 @@ inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
13661370
return DB;
13671371
}
13681372

1373+
inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
1374+
const llvm::APSInt *I) {
1375+
DB.AddTaggedVal(reinterpret_cast<intptr_t>(I), DiagnosticsEngine::ak_apsint);
1376+
return DB;
1377+
}
1378+
13691379
// We use enable_if here to prevent that this overload is selected for
13701380
// pointers or other arguments that are implicitly convertible to bool.
13711381
template <typename T>
@@ -1582,6 +1592,13 @@ class Diagnostic {
15821592
DiagStorage.DiagArgumentsVal[Idx]);
15831593
}
15841594

1595+
const llvm::APSInt *getArgAPSInt(unsigned Idx) const {
1596+
assert(getArgKind(Idx) == DiagnosticsEngine::ak_apsint &&
1597+
"invalid argument accessor!");
1598+
return reinterpret_cast<const llvm::APSInt *>(
1599+
DiagStorage.DiagArgumentsVal[Idx]);
1600+
}
1601+
15851602
/// Return the specified non-string argument in an opaque form.
15861603
/// \pre getArgKind(Idx) != DiagnosticsEngine::ak_std_string
15871604
uint64_t getRawArg(unsigned Idx) const {

clang/include/clang/Basic/DiagnosticSemaKinds.td

+4-4
Original file line numberDiff line numberDiff line change
@@ -6387,7 +6387,7 @@ def err_init_objc_class : Error<
63876387
def err_implicit_empty_initializer : Error<
63886388
"initializer for aggregate with no elements requires explicit braces">;
63896389
def err_bitfield_has_negative_width : Error<
6390-
"bit-field %0 has negative width (%1)">;
6390+
"bit-field %0 has negative width (%separated1)">;
63916391
def err_anon_bitfield_has_negative_width : Error<
63926392
"anonymous bit-field has negative width (%0)">;
63936393
def err_bitfield_has_zero_width : Error<"named bit-field %0 has zero width">;
@@ -6399,10 +6399,10 @@ def err_incorrect_number_of_vector_initializers : Error<
63996399

64006400
// Used by C++ which allows bit-fields that are wider than the type.
64016401
def warn_bitfield_width_exceeds_type_width: Warning<
6402-
"width of bit-field %0 (%1 bits) exceeds the width of its type; value will "
6403-
"be truncated to %2 bits">, InGroup<BitFieldWidth>;
6402+
"width of bit-field %0 (%separated1 bits) exceeds the width of its type; value will "
6403+
"be truncated to %separated2 bit%s2">, InGroup<BitFieldWidth>;
64046404
def err_bitfield_too_wide : Error<
6405-
"%select{bit-field %1|anonymous bit-field}0 is too wide (%2 bits)">;
6405+
"%select{bit-field %1|anonymous bit-field}0 is too wide (%separated2 bits)">;
64066406
def warn_bitfield_too_small_for_enum : Warning<
64076407
"bit-field %0 is not wide enough to store all enumerators of %1">,
64086408
InGroup<BitFieldEnumConversion>, DefaultIgnore;

clang/lib/Basic/Diagnostic.cpp

+29
Original file line numberDiff line numberDiff line change
@@ -769,6 +769,15 @@ static void HandleSelectModifier(const Diagnostic &DInfo, unsigned ValNo,
769769
DInfo.FormatDiagnostic(Argument, EndPtr, OutStr);
770770
}
771771

772+
static void HandleSeparatedModifier(const Diagnostic &DInfo,
773+
const llvm::APSInt &Val,
774+
const char *Argument, unsigned ArgumentLen,
775+
SmallVectorImpl<char> &OutStr) {
776+
llvm::raw_svector_ostream Out(OutStr);
777+
Out << toString(Val, 10, Val.isSigned(), /*formatAsCLiteral=*/false,
778+
/*UpperCase=*/false, /*InsertSeparators=*/true);
779+
}
780+
772781
/// HandleIntegerSModifier - Handle the integer 's' modifier. This adds the
773782
/// letter 's' to the string if the value is not 1. This is used in cases like
774783
/// this: "you idiot, you have %4 parameter%s4!".
@@ -1160,6 +1169,10 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
11601169
HandleOrdinalModifier((unsigned)Val, OutStr);
11611170
} else if (ModifierIs(Modifier, ModifierLen, "human")) {
11621171
HandleIntegerHumanModifier(Val, OutStr);
1172+
} else if (ModifierIs(Modifier, ModifierLen, "separated")) {
1173+
llvm::APSInt ValAP = llvm::APSInt(
1174+
llvm::APInt(64, Val, /*IsSigned=*/true), /*IsUnsigned=*/false);
1175+
HandleSeparatedModifier(*this, ValAP, Argument, ArgumentLen, OutStr);
11631176
} else {
11641177
assert(ModifierLen == 0 && "Unknown integer modifier");
11651178
llvm::raw_svector_ostream(OutStr) << Val;
@@ -1180,12 +1193,28 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
11801193
HandleOrdinalModifier(Val, OutStr);
11811194
} else if (ModifierIs(Modifier, ModifierLen, "human")) {
11821195
HandleIntegerHumanModifier(Val, OutStr);
1196+
} else if (ModifierIs(Modifier, ModifierLen, "separated")) {
1197+
llvm::APSInt ValAP = llvm::APSInt(
1198+
llvm::APInt(64, Val, /*IsSigned=*/false), /*IsUnsigned=*/true);
1199+
HandleSeparatedModifier(*this, ValAP, Argument, ArgumentLen, OutStr);
11831200
} else {
11841201
assert(ModifierLen == 0 && "Unknown integer modifier");
11851202
llvm::raw_svector_ostream(OutStr) << Val;
11861203
}
11871204
break;
11881205
}
1206+
1207+
case DiagnosticsEngine::ak_apsint: {
1208+
const llvm::APSInt *Val = getArgAPSInt(ArgNo);
1209+
if (ModifierIs(Modifier, ModifierLen, "separated")) {
1210+
HandleSeparatedModifier(*this, *Val, Argument, ArgumentLen, OutStr);
1211+
} else {
1212+
assert(ModifierLen == 0 && "Unknown integer modifier");
1213+
llvm::raw_svector_ostream(OutStr) << *Val;
1214+
}
1215+
// FIXME: Support the other modifiers for APSInt as well.
1216+
break;
1217+
}
11891218
// ---- TOKEN SPELLINGS ----
11901219
case DiagnosticsEngine::ak_tokenkind: {
11911220
tok::TokenKind Kind = static_cast<tok::TokenKind>(getRawArg(ArgNo));

clang/lib/Sema/SemaDecl.cpp

+5-20
Original file line numberDiff line numberDiff line change
@@ -18307,22 +18307,15 @@ ExprResult Sema::VerifyBitField(SourceLocation FieldLoc,
1830718307
if (Value.isSigned() && Value.isNegative()) {
1830818308
if (FieldName)
1830918309
return Diag(FieldLoc, diag::err_bitfield_has_negative_width)
18310-
<< FieldName
18311-
<< toString(Value, 10, Value.isSigned(),
18312-
/*formatAsCLiteral=*/false, /*UpperCase=*/true,
18313-
/*InsertSeparators=*/true);
18314-
return Diag(FieldLoc, diag::err_anon_bitfield_has_negative_width)
18315-
<< toString(Value, 10, Value.isSigned(), /*formatAsCLiteral=*/false,
18316-
/*UpperCase=*/true, /*InsertSeparators=*/true);
18310+
<< FieldName << &Value;
18311+
return Diag(FieldLoc, diag::err_anon_bitfield_has_negative_width) << &Value;
1831718312
}
1831818313

1831918314
// The size of the bit-field must not exceed our maximum permitted object
1832018315
// size.
1832118316
if (Value.getActiveBits() > ConstantArrayType::getMaxSizeBits(Context)) {
1832218317
return Diag(FieldLoc, diag::err_bitfield_too_wide)
18323-
<< !FieldName << FieldName
18324-
<< toString(Value, 10, Value.isSigned(), /*formatAsCLiteral=*/false,
18325-
/*UpperCase=*/true, /*InsertSeparators=*/true);
18318+
<< !FieldName << FieldName << &Value;
1832618319
}
1832718320

1832818321
if (!FieldTy->isDependentType()) {
@@ -18341,10 +18334,7 @@ ExprResult Sema::VerifyBitField(SourceLocation FieldLoc,
1834118334
unsigned DiagWidth =
1834218335
CStdConstraintViolation ? TypeWidth : TypeStorageSize;
1834318336
return Diag(FieldLoc, diag::err_bitfield_width_exceeds_type_width)
18344-
<< (bool)FieldName << FieldName
18345-
<< toString(Value, 10, Value.isSigned(),
18346-
/*formatAsCLiteral=*/false, /*UpperCase=*/true,
18347-
/*InsertSeparators=*/true)
18337+
<< (bool)FieldName << FieldName << &Value
1834818338
<< !CStdConstraintViolation << DiagWidth;
1834918339
}
1835018340

@@ -18355,12 +18345,7 @@ ExprResult Sema::VerifyBitField(SourceLocation FieldLoc,
1835518345
llvm::APInt TypeWidthAP(sizeof(TypeWidth) * 8, TypeWidth,
1835618346
/*IsSigned=*/false);
1835718347
Diag(FieldLoc, diag::warn_bitfield_width_exceeds_type_width)
18358-
<< FieldName
18359-
<< toString(Value, 10, Value.isSigned(), /*formatAsCLiteral=*/false,
18360-
/*UpperCase=*/true, /*InsertSeparators=*/true)
18361-
<< toString(TypeWidthAP, 10, /*Signed=*/false,
18362-
/*formatAsCLiteral=*/false, /*UpperCase=*/true,
18363-
/*InsertSeparators=*/true);
18348+
<< FieldName << &Value << (unsigned)TypeWidth;
1836418349
}
1836518350
}
1836618351

clang/utils/TableGen/ClangDiagnosticsEmitter.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,7 @@ enum ModifierType {
413413
MT_Diff,
414414
MT_Ordinal,
415415
MT_Human,
416+
MT_Separated,
416417
MT_S,
417418
MT_Q,
418419
MT_ObjCClass,
@@ -433,6 +434,8 @@ static StringRef getModifierName(ModifierType MT) {
433434
return "ordinal";
434435
case MT_Human:
435436
return "human";
437+
case MT_Separated:
438+
return "separated";
436439
case MT_S:
437440
return "s";
438441
case MT_Q:
@@ -1030,6 +1033,7 @@ Piece *DiagnosticTextBuilder::DiagText::parseDiagText(StringRef &Text,
10301033
.Case("s", MT_S)
10311034
.Case("ordinal", MT_Ordinal)
10321035
.Case("human", MT_Human)
1036+
.Case("separated", MT_Separated)
10331037
.Case("q", MT_Q)
10341038
.Case("objcclass", MT_ObjCClass)
10351039
.Case("objcinstance", MT_ObjCInstance)
@@ -1132,7 +1136,8 @@ Piece *DiagnosticTextBuilder::DiagText::parseDiagText(StringRef &Text,
11321136
case MT_ObjCClass:
11331137
case MT_ObjCInstance:
11341138
case MT_Ordinal:
1135-
case MT_Human: {
1139+
case MT_Human:
1140+
case MT_Separated: {
11361141
Parsed.push_back(New<PlaceholderPiece>(ModType, parseModifier(Text)));
11371142
continue;
11381143
}

0 commit comments

Comments
 (0)