summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorVolodymyr Sapsai <vsapsai@apple.com>2017-09-15 19:51:42 +0000
committerVolodymyr Sapsai <vsapsai@apple.com>2017-09-15 19:51:42 +0000
commit8b0bbc6fe03b50a87312902ed9ae2a09c5735889 (patch)
treefde62082dcbfe6b2b07d6a9c87da6d4d13c912a5 /clang
parente28adb4fb2a1f773e5f8ed5172df392fc4d40506 (diff)
downloadbcm5719-llvm-8b0bbc6fe03b50a87312902ed9ae2a09c5735889.tar.gz
bcm5719-llvm-8b0bbc6fe03b50a87312902ed9ae2a09c5735889.zip
[Sema] Error out early for tags defined inside an enumeration.
This fixes PR28903 by avoiding access check for inner enum constant. We are performing access check because one enum constant references another and because enum is defined in CXXRecordDecl. But access check doesn't work because FindDeclaringClass doesn't expect more than one EnumDecl and because inner enum has access AS_none due to not being an immediate child of a record. The change detects an enum is defined in wrong place and allows to skip parsing its body. Access check is skipped together with body parsing. There was no crash in C, added test case to cover the new error. rdar://problem/28530809 Reviewers: rnk, doug.gregor, rsmith Reviewed By: doug.gregor Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D37089 llvm-svn: 313386
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td2
-rw-r--r--clang/lib/Sema/SemaDecl.cpp6
-rw-r--r--clang/test/Sema/enum.c11
-rw-r--r--clang/test/SemaCXX/enum.cpp10
4 files changed, 29 insertions, 0 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 06c304f4359..dd628877f88 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1335,6 +1335,8 @@ def err_type_defined_in_alias_template : Error<
"%0 cannot be defined in a type alias template">;
def err_type_defined_in_condition : Error<
"%0 cannot be defined in a condition">;
+def err_type_defined_in_enum : Error<
+ "%0 cannot be defined in an enumeration">;
def note_pure_virtual_function : Note<
"unimplemented pure virtual method %0 in %1">;
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index d551f63b5fb..2cd93364869 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -13928,6 +13928,12 @@ CreateNewDecl:
Invalid = true;
}
+ if (!Invalid && TUK == TUK_Definition && DC->getDeclKind() == Decl::Enum) {
+ Diag(New->getLocation(), diag::err_type_defined_in_enum)
+ << Context.getTagDeclType(New);
+ Invalid = true;
+ }
+
// Maybe add qualifier info.
if (SS.isNotEmpty()) {
if (SS.isSet()) {
diff --git a/clang/test/Sema/enum.c b/clang/test/Sema/enum.c
index 3546bfe48fc..cf59ca1feff 100644
--- a/clang/test/Sema/enum.c
+++ b/clang/test/Sema/enum.c
@@ -123,3 +123,14 @@ int NegativeShortTest[NegativeShort == -1 ? 1 : -1];
// PR24610
enum Color { Red, Green, Blue }; // expected-note{{previous use is here}}
typedef struct Color NewColor; // expected-error {{use of 'Color' with tag type that does not match previous declaration}}
+
+// PR28903
+struct PR28903 {
+ enum {
+ PR28903_A = (enum { // expected-error-re {{'enum PR28903::(anonymous at {{.*}})' cannot be defined in an enumeration}}
+ PR28903_B,
+ PR28903_C = PR28903_B
+ })0
+ };
+ int makeStructNonEmpty;
+};
diff --git a/clang/test/SemaCXX/enum.cpp b/clang/test/SemaCXX/enum.cpp
index 6b0824b7514..cfe5760112f 100644
--- a/clang/test/SemaCXX/enum.cpp
+++ b/clang/test/SemaCXX/enum.cpp
@@ -110,3 +110,13 @@ enum { overflow = 123456 * 234567 };
// expected-warning@-2 {{not an integral constant expression}}
// expected-note@-3 {{value 28958703552 is outside the range of representable values}}
#endif
+
+// PR28903
+struct PR28903 {
+ enum {
+ PR28903_A = (enum { // expected-error-re {{'PR28903::(anonymous enum at {{.*}})' cannot be defined in an enumeration}}
+ PR28903_B,
+ PR28903_C = PR28903_B
+ })
+ };
+};
OpenPOWER on IntegriCloud