From 5e7b1eae1303a95061dab857dccb0ff15d5f943a Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Tue, 23 Oct 2018 19:44:51 +0000 Subject: [PATCH] Change getRedeclContext() to support enumerations as another kind of transparent context in C. This change fixes PR15071 and ensures that enumerators redefined in a struct cannot conflict with enumerators defined outside of the struct. llvm-svn: 345073 --- clang/lib/AST/DeclBase.cpp | 14 ++++++++++++-- clang/test/Sema/enum.c | 23 +++++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index f5de359..f65d306 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -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; } diff --git a/clang/test/Sema/enum.c b/clang/test/Sema/enum.c index f9e4069..7681ebc 100644 --- a/clang/test/Sema/enum.c +++ b/clang/test/Sema/enum.c @@ -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; +}; -- 2.7.4