[clang] 113b0d7 - PR46255: Fix field diagnostics for C records with anonymous members.

Erich Keane via cfe-commits cfe-commits at lists.llvm.org
Tue Jun 9 12:27:58 PDT 2020


Author: Erich Keane
Date: 2020-06-09T12:27:44-07:00
New Revision: 113b0d7d0bd637743efb050ad619dd0c6d306e96

URL: https://github.com/llvm/llvm-project/commit/113b0d7d0bd637743efb050ad619dd0c6d306e96
DIFF: https://github.com/llvm/llvm-project/commit/113b0d7d0bd637743efb050ad619dd0c6d306e96.diff

LOG: PR46255: Fix field diagnostics for C records with anonymous members.

The ParseStructUnionBody function was separately keeping track of the
field decls for historical reasons, however the "ActOn" functions add
the field to the RecordDecl anyway.

The "ParseStructDeclaration" function, which handles parsing fields
didn't have a way of handling what happens on an anonymous field, and
changing it would alter a large amount of objc code, so I chose instead
to implement this by just filling the FieldDecls vector with the actual
FieldDecls that were successfully added to the recorddecl .

Added: 
    

Modified: 
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/include/clang/Parse/Parser.h
    clang/lib/Parse/ParseDecl.cpp
    clang/lib/Parse/ParseDeclCXX.cpp
    clang/test/Sema/struct-decl.c

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 84bcf66a148e..e1adf199a12b 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5713,8 +5713,9 @@ def ext_flexible_array_union_gnu : Extension<
 def err_flexible_array_not_at_end : Error<
   "flexible array member %0 with type %1 is not at the end of"
   " %select{struct|interface|union|class|enum}2">;
-def err_objc_variable_sized_type_not_at_end : Error<
-  "field %0 with variable sized type %1 is not at the end of class">;
+def err_objc_variable_sized_type_not_at_end
+    : Error<"%select{field %1|unnamed field}0 with variable sized type %2 is "
+            "not at the end of class">;
 def note_next_field_declaration : Note<
   "next field declaration is here">;
 def note_next_ivar_declaration : Note<

diff  --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index b6b161e482ac..1ae219781c69 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -2333,7 +2333,7 @@ class Parser : public CodeCompletionHandler {
                           AccessSpecifier AS, DeclSpecContext DSC);
   void ParseEnumBody(SourceLocation StartLoc, Decl *TagDecl);
   void ParseStructUnionBody(SourceLocation StartLoc, DeclSpec::TST TagType,
-                            Decl *TagDecl);
+                            RecordDecl *TagDecl);
 
   void ParseStructDeclaration(
       ParsingDeclSpec &DS,

diff  --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 7e7619784557..79a3b19bac57 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -4249,7 +4249,7 @@ void Parser::ParseStructDeclaration(
 /// [OBC]   '@' 'defs' '(' class-name ')'
 ///
 void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
-                                  DeclSpec::TST TagType, Decl *TagDecl) {
+                                  DeclSpec::TST TagType, RecordDecl *TagDecl) {
   PrettyDeclStackTraceEntry CrashInfo(Actions.Context, TagDecl, RecordLoc,
                                       "parsing struct/union body");
   assert(!getLangOpts().CPlusPlus && "C++ declarations not supported");
@@ -4261,8 +4261,6 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
   ParseScope StructScope(this, Scope::ClassScope|Scope::DeclScope);
   Actions.ActOnTagStartDefinition(getCurScope(), TagDecl);
 
-  SmallVector<Decl *, 32> FieldDecls;
-
   // While we still have something to read, read the declarations in the struct.
   while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) &&
          Tok.isNot(tok::eof)) {
@@ -4314,7 +4312,6 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
             Actions.ActOnField(getCurScope(), TagDecl,
                                FD.D.getDeclSpec().getSourceRange().getBegin(),
                                FD.D, FD.BitfieldSize);
-        FieldDecls.push_back(Field);
         FD.complete(Field);
       };
 
@@ -4338,7 +4335,6 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
       SmallVector<Decl *, 16> Fields;
       Actions.ActOnDefs(getCurScope(), TagDecl, Tok.getLocation(),
                         Tok.getIdentifierInfo(), Fields);
-      FieldDecls.insert(FieldDecls.end(), Fields.begin(), Fields.end());
       ConsumeToken();
       ExpectAndConsume(tok::r_paren);
     }
@@ -4364,6 +4360,9 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
   // If attributes exist after struct contents, parse them.
   MaybeParseGNUAttributes(attrs);
 
+  SmallVector<Decl *, 32> FieldDecls(TagDecl->field_begin(),
+                                     TagDecl->field_end());
+
   Actions.ActOnFields(getCurScope(), RecordLoc, TagDecl, FieldDecls,
                       T.getOpenLocation(), T.getCloseLocation(), attrs);
   StructScope.Exit();

diff  --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 1a82475117ba..8753c9292875 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -1964,7 +1964,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
       Decl *D =
           SkipBody.CheckSameAsPrevious ? SkipBody.New : TagOrTempResult.get();
       // Parse the definition body.
-      ParseStructUnionBody(StartLoc, TagType, D);
+      ParseStructUnionBody(StartLoc, TagType, cast<RecordDecl>(D));
       if (SkipBody.CheckSameAsPrevious &&
           !Actions.ActOnDuplicateDefinition(DS, TagOrTempResult.get(),
                                             SkipBody)) {

diff  --git a/clang/test/Sema/struct-decl.c b/clang/test/Sema/struct-decl.c
index 80cac0e0d145..ee3e79182eaa 100644
--- a/clang/test/Sema/struct-decl.c
+++ b/clang/test/Sema/struct-decl.c
@@ -69,3 +69,44 @@ void test_hiding() {
 
 struct PreserveAttributes {};
 typedef struct __attribute__((noreturn)) PreserveAttributes PreserveAttributes_t; // expected-warning {{'noreturn' attribute only applies to functions and methods}}
+
+// PR46255
+struct FlexibleArrayMem {
+  int a;
+  int b[];
+};
+
+struct FollowedByNamed {
+  struct FlexibleArrayMem a; // expected-warning {{field 'a' with variable sized type 'struct FlexibleArrayMem' not at the end of a struct or class is a GNU extension}}
+  int i;
+};
+
+struct FollowedByUnNamed {
+  struct FlexibleArrayMem a; // expected-warning {{field 'a' with variable sized type 'struct FlexibleArrayMem' not at the end of a struct or class is a GNU extension}}
+  struct {
+    int i;
+  };
+};
+
+struct InAnonymous {
+  struct { // expected-warning-re {{field '' with variable sized type 'struct InAnonymous::(anonymous at {{.+}})' not at the end of a struct or class is a GNU extension}}
+
+    struct FlexibleArrayMem a;
+  };
+  int i;
+};
+struct InAnonymousFollowedByAnon {
+  struct { // expected-warning-re {{field '' with variable sized type 'struct InAnonymousFollowedByAnon::(anonymous at {{.+}})' not at the end of a struct or class is a GNU extension}}
+
+    struct FlexibleArrayMem a;
+  };
+  struct {
+    int i;
+  };
+};
+
+// This is the behavior in C++ as well, so making sure we reproduce it here.
+struct InAnonymousFollowedByEmpty {
+  struct FlexibleArrayMem a; // expected-warning {{field 'a' with variable sized type 'struct FlexibleArrayMem' not at the end of a struct or class is a GNU extension}}
+  struct {};
+};


        


More information about the cfe-commits mailing list