Skip to content

Commit 2e8e254

Browse files
authored
[Clang] include attribute scope in diagnostics (#144619)
This patch updates diagnostics to print fully qualified attribute names, including scope when present.
1 parent 763131b commit 2e8e254

File tree

96 files changed

+505
-493
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

96 files changed

+505
-493
lines changed

clang/include/clang/Basic/AttributeCommonInfo.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#define LLVM_CLANG_BASIC_ATTRIBUTECOMMONINFO_H
1616

1717
#include "clang/Basic/AttributeScopeInfo.h"
18+
#include "clang/Basic/Diagnostic.h"
1819
#include "clang/Basic/SourceLocation.h"
1920
#include "clang/Basic/TokenKinds.h"
2021

@@ -175,6 +176,10 @@ class AttributeCommonInfo {
175176
: AttributeCommonInfo(nullptr, AttributeScopeInfo(), AttrRange, K,
176177
FormUsed) {}
177178

179+
AttributeCommonInfo(SourceRange AttrRange, AttributeScopeInfo AttrScope,
180+
Kind K, Form FormUsed)
181+
: AttributeCommonInfo(nullptr, AttrScope, AttrRange, K, FormUsed) {}
182+
178183
AttributeCommonInfo(AttributeCommonInfo &&) = default;
179184
AttributeCommonInfo(const AttributeCommonInfo &) = default;
180185

@@ -292,6 +297,18 @@ inline bool doesKeywordAttributeTakeArgs(tok::TokenKind Kind) {
292297
}
293298
}
294299

300+
inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
301+
const AttributeCommonInfo *CI) {
302+
DB.AddTaggedVal(reinterpret_cast<uint64_t>(CI),
303+
DiagnosticsEngine::ak_attr_info);
304+
return DB;
305+
}
306+
307+
inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
308+
const AttributeCommonInfo &CI) {
309+
return DB << &CI;
310+
}
311+
295312
} // namespace clang
296313

297314
#endif // LLVM_CLANG_BASIC_ATTRIBUTECOMMONINFO_H

clang/include/clang/Basic/Diagnostic.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,9 @@ class DiagnosticsEngine : public RefCountedBase<DiagnosticsEngine> {
289289

290290
/// Expr *
291291
ak_expr,
292+
293+
/// AttributeCommonInfo *
294+
ak_attr_info,
292295
};
293296

294297
/// Represents on argument value, which is a union discriminated

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3290,10 +3290,11 @@ def err_attribute_wrong_number_arguments : Error<
32903290
def err_attribute_wrong_number_arguments_for : Error <
32913291
"%0 attribute references function %1, which %plural{0:takes no arguments|1:takes one argument|"
32923292
":takes exactly %2 arguments}2">;
3293-
def err_callback_attribute_wrong_arg_count : Error<
3294-
"'callback' attribute references function of type %0 which expects %1 "
3295-
"%plural{1:argument|:arguments}1 but attribute specifies %2 parameter index "
3296-
"%plural{1:argument|:arguments}2">;
3293+
def err_attribute_wrong_arg_count_for_func
3294+
: Error<"%0 attribute references function of type %1 which expects %2 "
3295+
"%plural{1:argument|:arguments}2 but attribute specifies %3 "
3296+
"parameter index "
3297+
"%plural{1:argument|:arguments}3">;
32973298
def err_attribute_bounds_for_function : Error<
32983299
"%0 attribute references parameter %1, but the function %2 has only %3 parameters">;
32993300
def err_attribute_no_member_function : Error<
@@ -4712,9 +4713,9 @@ def note_protocol_decl : Note<
47124713
"protocol is declared here">;
47134714
def note_protocol_decl_undefined : Note<
47144715
"protocol %0 has no definition">;
4715-
def err_attribute_preferred_name_arg_invalid : Error<
4716-
"argument %0 to 'preferred_name' attribute is not a typedef for "
4717-
"a specialization of %1">;
4716+
def err_attribute_not_typedef_for_specialization
4717+
: Error<"argument %0 to %1 attribute is not a typedef for "
4718+
"a specialization of %2">;
47184719
def err_attribute_builtin_alias : Error<
47194720
"%0 attribute can only be applied to a ARM, HLSL, SPIR-V or RISC-V builtin">;
47204721

clang/include/clang/Sema/ParsedAttr.h

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1094,45 +1094,6 @@ enum AttributeDeclKind {
10941094
ExpectedTypedef,
10951095
};
10961096

1097-
inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
1098-
const ParsedAttr &At) {
1099-
DB.AddTaggedVal(reinterpret_cast<uint64_t>(At.getAttrName()),
1100-
DiagnosticsEngine::ak_identifierinfo);
1101-
return DB;
1102-
}
1103-
1104-
inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
1105-
const ParsedAttr *At) {
1106-
DB.AddTaggedVal(reinterpret_cast<uint64_t>(At->getAttrName()),
1107-
DiagnosticsEngine::ak_identifierinfo);
1108-
return DB;
1109-
}
1110-
1111-
/// AttributeCommonInfo has a non-explicit constructor which takes an
1112-
/// SourceRange as its only argument, this constructor has many uses so making
1113-
/// it explicit is hard. This constructor causes ambiguity with
1114-
/// DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, SourceRange R).
1115-
/// We use SFINAE to disable any conversion and remove any ambiguity.
1116-
template <
1117-
typename ACI,
1118-
std::enable_if_t<std::is_same<ACI, AttributeCommonInfo>::value, int> = 0>
1119-
inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
1120-
const ACI &CI) {
1121-
DB.AddTaggedVal(reinterpret_cast<uint64_t>(CI.getAttrName()),
1122-
DiagnosticsEngine::ak_identifierinfo);
1123-
return DB;
1124-
}
1125-
1126-
template <
1127-
typename ACI,
1128-
std::enable_if_t<std::is_same<ACI, AttributeCommonInfo>::value, int> = 0>
1129-
inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
1130-
const ACI *CI) {
1131-
DB.AddTaggedVal(reinterpret_cast<uint64_t>(CI->getAttrName()),
1132-
DiagnosticsEngine::ak_identifierinfo);
1133-
return DB;
1134-
}
1135-
11361097
} // namespace clang
11371098

11381099
#endif // LLVM_CLANG_SEMA_PARSEDATTR_H

clang/lib/AST/ASTDiagnostic.cpp

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -506,7 +506,15 @@ void clang::FormatASTNodeDiagnosticArgument(
506506
case DiagnosticsEngine::ak_attr: {
507507
const Attr *At = reinterpret_cast<Attr *>(Val);
508508
assert(At && "Received null Attr object!");
509-
OS << '\'' << At->getSpelling() << '\'';
509+
510+
OS << '\'';
511+
if (At->hasScope()) {
512+
OS << At->getNormalizedFullName(At->getScopeName()->getName(),
513+
At->getSpelling());
514+
} else {
515+
OS << At->getSpelling();
516+
}
517+
OS << '\'';
510518
NeedQuotes = false;
511519
break;
512520
}
@@ -516,6 +524,20 @@ void clang::FormatASTNodeDiagnosticArgument(
516524
E->printPretty(OS, /*Helper=*/nullptr, Context.getPrintingPolicy());
517525
break;
518526
}
527+
case DiagnosticsEngine::ak_attr_info: {
528+
AttributeCommonInfo *AT = reinterpret_cast<AttributeCommonInfo *>(Val);
529+
assert(AT && "Received null AttributeCommonInfo object!");
530+
531+
OS << '\'';
532+
if (AT->isStandardAttributeSyntax()) {
533+
OS << AT->getNormalizedFullName();
534+
} else {
535+
OS << AT->getAttrName()->getName();
536+
}
537+
OS << '\'';
538+
NeedQuotes = false;
539+
break;
540+
}
519541
}
520542

521543
if (NeedQuotes) {

clang/lib/Basic/Diagnostic.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1348,6 +1348,7 @@ void Diagnostic::FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
13481348
case DiagnosticsEngine::ak_declcontext:
13491349
case DiagnosticsEngine::ak_attr:
13501350
case DiagnosticsEngine::ak_expr:
1351+
case DiagnosticsEngine::ak_attr_info:
13511352
getDiags()->ConvertArgToString(Kind, getRawArg(ArgNo),
13521353
StringRef(Modifier, ModifierLen),
13531354
StringRef(Argument, ArgumentLen),

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1226,8 +1226,8 @@ static void handlePreferredName(Sema &S, Decl *D, const ParsedAttr &AL) {
12261226
}
12271227
}
12281228

1229-
S.Diag(AL.getLoc(), diag::err_attribute_preferred_name_arg_invalid)
1230-
<< T << CTD;
1229+
S.Diag(AL.getLoc(), diag::err_attribute_not_typedef_for_specialization)
1230+
<< T << AL << CTD;
12311231
if (const auto *TT = T->getAs<TypedefType>())
12321232
S.Diag(TT->getDecl()->getLocation(), diag::note_entity_declared_at)
12331233
<< TT->getDecl();
@@ -4194,8 +4194,9 @@ static void handleCallbackAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
41944194
}
41954195

41964196
if (CalleeFnProtoType->getNumParams() != EncodingIndices.size() - 1) {
4197-
S.Diag(AL.getLoc(), diag::err_callback_attribute_wrong_arg_count)
4198-
<< QualType{CalleeFnProtoType, 0} << CalleeFnProtoType->getNumParams()
4197+
S.Diag(AL.getLoc(), diag::err_attribute_wrong_arg_count_for_func)
4198+
<< AL << QualType{CalleeFnProtoType, 0}
4199+
<< CalleeFnProtoType->getNumParams()
41994200
<< (unsigned)(EncodingIndices.size() - 1);
42004201
return;
42014202
}
@@ -8020,9 +8021,7 @@ void Sema::checkUnusedDeclAttributes(Declarator &D) {
80208021
}
80218022

80228023
void Sema::DiagnoseUnknownAttribute(const ParsedAttr &AL) {
8023-
std::string NormalizedFullName = '\'' + AL.getNormalizedFullName() + '\'';
80248024
SourceRange NR = AL.getNormalizedRange();
8025-
80268025
StringRef ScopeName = AL.getNormalizedScopeName();
80278026
std::optional<StringRef> CorrectedScopeName =
80288027
AL.tryGetCorrectedScopeName(ScopeName);
@@ -8044,7 +8043,7 @@ void Sema::DiagnoseUnknownAttribute(const ParsedAttr &AL) {
80448043
Diag(CorrectedScopeName ? NR.getBegin() : AL.getRange().getBegin(),
80458044
diag::warn_unknown_attribute_ignored_suggestion);
80468045

8047-
D << NormalizedFullName << CorrectedFullName;
8046+
D << AL << CorrectedFullName;
80488047

80498048
if (AL.isExplicitScope()) {
80508049
D << FixItHint::CreateReplacement(NR, CorrectedFullName) << NR;
@@ -8058,8 +8057,7 @@ void Sema::DiagnoseUnknownAttribute(const ParsedAttr &AL) {
80588057
}
80598058
}
80608059
} else {
8061-
Diag(NR.getBegin(), diag::warn_unknown_attribute_ignored)
8062-
<< NormalizedFullName << NR;
8060+
Diag(NR.getBegin(), diag::warn_unknown_attribute_ignored) << AL << NR;
80638061
}
80648062
}
80658063

clang/lib/Sema/SemaHLSL.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1640,6 +1640,15 @@ bool SemaHLSL::handleResourceTypeAttr(QualType T, const ParsedAttr &AL) {
16401640
return false;
16411641

16421642
Attr *A = nullptr;
1643+
1644+
AttributeCommonInfo ACI(
1645+
AL.getLoc(), AttributeScopeInfo(AL.getScopeName(), AL.getScopeLoc()),
1646+
AttributeCommonInfo::NoSemaHandlerAttribute,
1647+
{
1648+
AttributeCommonInfo::AS_CXX11, 0, false /*IsAlignas*/,
1649+
false /*IsRegularKeywordAttribute*/
1650+
});
1651+
16431652
switch (AL.getKind()) {
16441653
case ParsedAttr::AT_HLSLResourceClass: {
16451654
if (!AL.isArgIdent(0)) {
@@ -1659,16 +1668,16 @@ bool SemaHLSL::handleResourceTypeAttr(QualType T, const ParsedAttr &AL) {
16591668
<< "ResourceClass" << Identifier;
16601669
return false;
16611670
}
1662-
A = HLSLResourceClassAttr::Create(getASTContext(), RC, AL.getLoc());
1671+
A = HLSLResourceClassAttr::Create(getASTContext(), RC, ACI);
16631672
break;
16641673
}
16651674

16661675
case ParsedAttr::AT_HLSLROV:
1667-
A = HLSLROVAttr::Create(getASTContext(), AL.getLoc());
1676+
A = HLSLROVAttr::Create(getASTContext(), ACI);
16681677
break;
16691678

16701679
case ParsedAttr::AT_HLSLRawBuffer:
1671-
A = HLSLRawBufferAttr::Create(getASTContext(), AL.getLoc());
1680+
A = HLSLRawBufferAttr::Create(getASTContext(), ACI);
16721681
break;
16731682

16741683
case ParsedAttr::AT_HLSLContainedType: {
@@ -1683,7 +1692,7 @@ bool SemaHLSL::handleResourceTypeAttr(QualType T, const ParsedAttr &AL) {
16831692
if (SemaRef.RequireCompleteType(TSI->getTypeLoc().getBeginLoc(), QT,
16841693
diag::err_incomplete_type))
16851694
return false;
1686-
A = HLSLContainedTypeAttr::Create(getASTContext(), TSI, AL.getLoc());
1695+
A = HLSLContainedTypeAttr::Create(getASTContext(), TSI, ACI);
16871696
break;
16881697
}
16891698

clang/test/AST/ByteCode/functions.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -637,7 +637,7 @@ namespace {
637637

638638
namespace {
639639
/// The InitListExpr here is of void type.
640-
void bir [[clang::annotate("B", {1, 2, 3, 4})]] (); // both-error {{'annotate' attribute requires parameter 1 to be a constant expression}} \
640+
void bir [[clang::annotate("B", {1, 2, 3, 4})]] (); // both-error {{'clang::annotate' attribute requires parameter 1 to be a constant expression}} \
641641
// both-note {{subexpression not valid in a constant expression}}
642642
}
643643

clang/test/C/C23/n3037.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ union purr { float y; int x; }; // c23-error {{type 'union purr' has incompatibl
6060

6161
// The presence of an attribute makes two types not compatible.
6262
struct [[gnu::packed]] attr_test { // c17-note {{previous definition is here}} \
63-
c23-note {{attribute 'packed' here}}
63+
c23-note {{attribute 'gnu::packed' here}}
6464
int x;
6565
};
6666

@@ -75,26 +75,26 @@ struct attr_test_2 { // c17-note {{previous definition is here}}
7575

7676
struct [[gnu::packed]] attr_test_2 { // c17-error {{redefinition of 'attr_test_2'}} \
7777
c23-error {{type 'struct attr_test_2' has an attribute which currently causes the types to be treated as though they are incompatible}} \
78-
c23-note {{attribute 'packed' here}}
78+
c23-note {{attribute 'gnu::packed' here}}
7979
int x;
8080
};
8181

8282
// This includes the same attribute on both types.
8383
struct [[gnu::packed]] attr_test_3 { // c17-note {{previous definition is here}} \
84-
c23-note {{attribute 'packed' here}}
84+
c23-note {{attribute 'gnu::packed' here}}
8585
int x;
8686
};
8787

8888
struct [[gnu::packed]] attr_test_3 { // c17-error {{redefinition of 'attr_test_3'}} \
8989
c23-error {{type 'struct attr_test_3' has an attribute which currently causes the types to be treated as though they are incompatible}} \
90-
c23-note {{attribute 'packed' here}}
90+
c23-note {{attribute 'gnu::packed' here}}
9191
int x;
9292
};
9393

9494
// Everything which applies to the tag itself also applies to fields.
9595
struct field_attr_test_1 { // c17-note {{previous definition is here}}
9696
int x;
97-
[[gnu::packed]] int y; // c23-note {{attribute 'packed' here}}
97+
[[gnu::packed]] int y; // c23-note {{attribute 'gnu::packed' here}}
9898
};
9999

100100
struct field_attr_test_1 { // c17-error {{redefinition of 'field_attr_test_1'}} \
@@ -104,7 +104,7 @@ struct field_attr_test_1 { // c17-error {{redefinition of 'field_attr_test_1'}}
104104
};
105105

106106
struct field_attr_test_2 { // c17-note {{previous definition is here}}
107-
[[gnu::packed]] int x; // c23-note {{attribute 'packed' here}}
107+
[[gnu::packed]] int x; // c23-note {{attribute 'gnu::packed' here}}
108108
int y;
109109
};
110110

@@ -115,13 +115,13 @@ struct field_attr_test_2 { // c17-error {{redefinition of 'field_attr_test_2'}}
115115
};
116116

117117
struct field_attr_test_3 { // c17-note {{previous definition is here}}
118-
[[gnu::packed]] int x; // c23-note {{attribute 'packed' here}}
118+
[[gnu::packed]] int x; // c23-note {{attribute 'gnu::packed' here}}
119119
int y;
120120
};
121121

122122
struct field_attr_test_3 { // c17-error {{redefinition of 'field_attr_test_3'}} \
123123
c23-error {{type 'struct field_attr_test_3' has a member with an attribute which currently causes the types to be treated as though they are incompatible}}
124-
int x [[gnu::packed]]; // c23-note {{attribute 'packed' here}}
124+
int x [[gnu::packed]]; // c23-note {{attribute 'gnu::packed' here}}
125125
int y;
126126
};
127127

0 commit comments

Comments
 (0)