]> granicus.if.org Git - clang/commitdiff
Change getRedeclContext() to support enumerations as another kind of transparent...
authorAaron Ballman <aaron@aaronballman.com>
Tue, 23 Oct 2018 19:44:51 +0000 (19:44 +0000)
committerAaron Ballman <aaron@aaronballman.com>
Tue, 23 Oct 2018 19:44:51 +0000 (19:44 +0000)
This change fixes PR15071 and ensures that enumerators redefined in a struct cannot conflict with enumerators defined outside of the struct.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@345073 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/DeclBase.cpp
test/Sema/enum.c

index f5de359106573e7ab96fa4b032559f7ede73009b..f65d3063e37bc0a630f3902cafffa08a673c1225 100644 (file)
@@ -1724,8 +1724,18 @@ void DeclContext::localUncachedLookup(DeclarationName Name,
 
 DeclContext *DeclContext::getRedeclContext() {
   DeclContext *Ctx = this;
-  // Skip through transparent contexts.
-  while (Ctx->isTransparentContext())
+
+  // In C, a record type is the redeclaration context for its fields only. If
+  // we arrive at a record context after skipping anything else, we should skip
+  // the record as well. Currently, this means skipping enumerations because
+  // they're the only transparent context that can exist within a struct or
+  // union.
+  bool SkipRecords = getDeclKind() == Decl::Kind::Enum &&
+                     !getParentASTContext().getLangOpts().CPlusPlus;
+
+  // Skip through contexts to get to the redeclaration context. Transparent
+  // contexts are always skipped.
+  while ((SkipRecords && Ctx->isRecord()) || Ctx->isTransparentContext())
     Ctx = Ctx->getParent();
   return Ctx;
 }
index f9e40690c6a6d70b0d9ff60b9283fcda8f7d6a39..7681ebccd4fa86d6fd497c6dd128d7d03d24121f 100644 (file)
@@ -135,3 +135,26 @@ struct PR28903 {
   };
   int makeStructNonEmpty;
 };
+
+static int EnumRedecl; // expected-note 2 {{previous definition is here}}
+struct S {
+  enum {
+    EnumRedecl = 4 // expected-error {{redefinition of 'EnumRedecl'}}
+  } e;
+};
+
+union U {
+  enum {
+    EnumRedecl = 5 // expected-error {{redefinition of 'EnumRedecl'}}
+  } e;
+};
+
+enum PR15071 {
+  PR15071_One // expected-note {{previous definition is here}}
+};
+
+struct EnumRedeclStruct {
+  enum {
+    PR15071_One // expected-error {{redefinition of enumerator 'PR15071_One'}}
+  } e;
+};