Skip to content

Commit 444bfc5

Browse files
committed
track enum key source range in EnumDecl
1 parent 253af19 commit 444bfc5

File tree

4 files changed

+39
-23
lines changed

4 files changed

+39
-23
lines changed

clang/include/clang/AST/Decl.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4040,6 +4040,11 @@ class EnumDecl : public TagDecl {
40404040
/// and can be accessed with the provided accessors.
40414041
unsigned ODRHash;
40424042

4043+
/// Source range covering the enum key:
4044+
/// - 'enum' (unscoped)
4045+
/// - 'enum class|struct' (scoped)
4046+
SourceRange EnumKeyRange;
4047+
40434048
EnumDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
40444049
SourceLocation IdLoc, IdentifierInfo *Id, EnumDecl *PrevDecl,
40454050
bool Scoped, bool ScopedUsingClassTag, bool Fixed);
@@ -4077,6 +4082,10 @@ class EnumDecl : public TagDecl {
40774082
/// Microsoft-style enumeration with a fixed underlying type.
40784083
void setFixed(bool Fixed = true) { EnumDeclBits.IsFixed = Fixed; }
40794084

4085+
SourceRange getEnumKeyRange() const { return EnumKeyRange; }
4086+
4087+
void setEnumKeyRange(SourceRange Range) { EnumKeyRange = Range; }
4088+
40804089
private:
40814090
/// True if a valid hash is stored in ODRHash.
40824091
bool hasODRHash() const { return EnumDeclBits.HasODRHash; }

clang/lib/Parse/Parser.cpp

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1107,16 +1107,8 @@ Parser::DeclGroupPtrTy Parser::ParseDeclOrFunctionDefInternal(
11071107
if (DeclSpec::isDeclRep(TKind)) {
11081108
if (TKind == DeclSpec::TST_enum) {
11091109
if (const auto *ED = dyn_cast_or_null<EnumDecl>(DS.getRepAsDecl())) {
1110-
if (ED->getIdentifier()) {
1111-
CorrectLocationForAttributes = ED->getLocation();
1112-
} else {
1113-
SourceLocation Begin = ED->getBraceRange().getBegin();
1114-
CorrectLocationForAttributes =
1115-
Begin.isValid() ? Begin :
1116-
// If there is no brace, fall back to the end
1117-
// location, which corresponds to the semicolon.
1118-
ED->getEndLoc();
1119-
}
1110+
CorrectLocationForAttributes =
1111+
PP.getLocForEndOfToken(ED->getEnumKeyRange().getEnd());
11201112
}
11211113
}
11221114
if (CorrectLocationForAttributes.isInvalid()) {

clang/lib/Sema/SemaDecl.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18457,17 +18457,21 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
1845718457
cast_or_null<EnumDecl>(PrevDecl), ScopedEnum,
1845818458
ScopedEnumUsesClassTag, IsFixed);
1845918459

18460+
EnumDecl *ED = cast<EnumDecl>(New);
18461+
ED->setEnumKeyRange(SourceRange(
18462+
KWLoc, ScopedEnumKWLoc.isValid() ? ScopedEnumKWLoc : KWLoc));
18463+
1846018464
if (isStdAlignValT && (!StdAlignValT || getStdAlignValT()->isImplicit()))
1846118465
StdAlignValT = cast<EnumDecl>(New);
1846218466

1846318467
// If this is an undefined enum, warn.
1846418468
if (TUK != TagUseKind::Definition && !Invalid) {
1846518469
TagDecl *Def;
18466-
if (IsFixed && cast<EnumDecl>(New)->isFixed()) {
18470+
if (IsFixed && ED->isFixed()) {
1846718471
// C++0x: 7.2p2: opaque-enum-declaration.
1846818472
// Conflicts are diagnosed above. Do nothing.
18469-
}
18470-
else if (PrevDecl && (Def = cast<EnumDecl>(PrevDecl)->getDefinition())) {
18473+
} else if (PrevDecl &&
18474+
(Def = cast<EnumDecl>(PrevDecl)->getDefinition())) {
1847118475
Diag(Loc, diag::ext_forward_ref_enum_def)
1847218476
<< New;
1847318477
Diag(Def->getLocation(), diag::note_previous_definition);

clang/test/FixIt/fixit-cxx0x-attributes.cpp

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,45 @@
44
[[nodiscard]] enum class E1 { };
55
// expected-error@-1 {{misplaced attributes; expected attributes here}}
66
// CHECK: {{^}}{{\[\[}}nodiscard]] enum class E1 { };
7-
// CHECK: {{^}}~~~~~~~~~~~~~ ^
7+
// CHECK: {{^}}~~~~~~~~~~~~~ ^
88
// CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:1-[[@LINE-4]]:15}:""
9-
// CHECK: fix-it:"{{.*}}":{[[@LINE-5]]:26-[[@LINE-5]]:26}:"{{\[\[}}nodiscard]]"
9+
// CHECK: fix-it:"{{.*}}":{[[@LINE-5]]:25-[[@LINE-5]]:25}:"{{\[\[}}nodiscard]]"
1010

1111
[[nodiscard]] enum struct E2 { };
1212
// expected-error@-1 {{misplaced attributes; expected attributes here}}
1313
// CHECK: {{^}}{{\[\[}}nodiscard]] enum struct E2 { };
14-
// CHECK: {{^}}~~~~~~~~~~~~~ ^
14+
// CHECK: {{^}}~~~~~~~~~~~~~ ^
1515
// CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:1-[[@LINE-4]]:15}:""
16-
// CHECK: fix-it:"{{.*}}":{[[@LINE-5]]:27-[[@LINE-5]]:27}:"{{\[\[}}nodiscard]]"
16+
// CHECK: fix-it:"{{.*}}":{[[@LINE-5]]:26-[[@LINE-5]]:26}:"{{\[\[}}nodiscard]]"
1717

1818
[[nodiscard]] enum class E3 { };
1919
// expected-error@-1 {{misplaced attributes; expected attributes here}}
2020
// CHECK: {{^}}{{\[\[}}nodiscard]] enum class E3 { };
21-
// CHECK: {{^}}~~~~~~~~~~~~~ ^
21+
// CHECK: {{^}}~~~~~~~~~~~~~ ^
2222
// CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:1-[[@LINE-4]]:15}:""
23-
// CHECK: fix-it:"{{.*}}":{[[@LINE-5]]:35-[[@LINE-5]]:35}:"{{\[\[}}nodiscard]]"
23+
// CHECK: fix-it:"{{.*}}":{[[@LINE-5]]:34-[[@LINE-5]]:34}:"{{\[\[}}nodiscard]]"
2424

2525
[[nodiscard]] enum /*comment*/ class E4 { };
2626
// expected-error@-1 {{misplaced attributes; expected attributes here}}
2727
// CHECK: {{^}}{{\[\[}}nodiscard]] enum /*comment*/ class E4 { };
28-
// CHECK: {{^}}~~~~~~~~~~~~~ ^
28+
// CHECK: {{^}}~~~~~~~~~~~~~ ^
2929
// CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:1-[[@LINE-4]]:15}:""
30-
// CHECK: fix-it:"{{.*}}":{[[@LINE-5]]:39-[[@LINE-5]]:39}:"{{\[\[}}nodiscard]]"
30+
// CHECK: fix-it:"{{.*}}":{[[@LINE-5]]:38-[[@LINE-5]]:38}:"{{\[\[}}nodiscard]]"
3131

3232
[[nodiscard]] enum { A = 0 };
3333
// expected-error@-1 {{misplaced attributes; expected attributes here}}
3434
// CHECK: {{^}}{{\[\[}}nodiscard]] enum { A = 0 };
35-
// CHECK: {{^}}~~~~~~~~~~~~~ ^
35+
// CHECK: {{^}}~~~~~~~~~~~~~ ^
36+
// CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:1-[[@LINE-4]]:15}:""
37+
// CHECK: fix-it:"{{.*}}":{[[@LINE-5]]:19-[[@LINE-5]]:19}:"{{\[\[}}nodiscard]]"
38+
39+
namespace NS {
40+
enum class E5;
41+
}
42+
43+
[[nodiscard]] enum class NS::E5 { };
44+
// expected-error@-1 {{misplaced attributes; expected attributes here}}
45+
// CHECK: {{^}}{{\[\[}}nodiscard]] enum class NS::E5 { };
46+
// CHECK: {{^}}~~~~~~~~~~~~~ ^
3647
// CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:1-[[@LINE-4]]:15}:""
37-
// CHECK: fix-it:"{{.*}}":{[[@LINE-5]]:20-[[@LINE-5]]:20}:"{{\[\[}}nodiscard]]"
48+
// CHECK: fix-it:"{{.*}}":{[[@LINE-5]]:25-[[@LINE-5]]:25}:"{{\[\[}}nodiscard]]"

0 commit comments

Comments
 (0)