[clang] 63342ae - Fix a failing assertion with implicit function definitions

Aaron Ballman via cfe-commits cfe-commits at lists.llvm.org
Fri Jun 23 04:04:49 PDT 2023


Author: Aaron Ballman
Date: 2023-06-23T07:02:21-04:00
New Revision: 63342ae4b8f7573fd03fdb6eb38d55097b9a6922

URL: https://github.com/llvm/llvm-project/commit/63342ae4b8f7573fd03fdb6eb38d55097b9a6922
DIFF: https://github.com/llvm/llvm-project/commit/63342ae4b8f7573fd03fdb6eb38d55097b9a6922.diff

LOG: Fix a failing assertion with implicit function definitions

When implicitly defining a function in C, we would try to find an
appropriate declaration context for the function to be declared within.
However, we did not account for GNU statement expressions, which
masquerade as a compound statement and can be used in other contexts
such as within structure member declarations.

Fixes https://github.com/llvm/llvm-project/issues/48579

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/lib/Sema/SemaDecl.cpp
    clang/test/Sema/implicit-decl.c

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 7c6a350c7eab2..52669132be889 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -524,6 +524,10 @@ Bug Fixes in This Version
   type by the default argument promotions, and thus this is UB. Clang's
   behavior now matches GCC's behavior in C++.
   (`#38717 <https://github.com/llvm/llvm-project/issues/38717>_`).
+- Fixed a failing assertion when implicitly defining a function within a GNU
+  statement expression that appears outside of a function block scope. The
+  assertion was benign outside of asserts builds and would only fire in C.
+  (`#48579 <https://github.com/llvm/llvm-project/issues/48579>_`).
 
 Bug Fixes to Compiler Builtins
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 27cb9695e9424..9fe1cb20a76f6 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -16000,8 +16000,14 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
   while (!BlockScope->isCompoundStmtScope() && BlockScope->getParent())
     BlockScope = BlockScope->getParent();
 
+  // Loop until we find a DeclContext that is either a function/method or the
+  // translation unit, which are the only two valid places to implicitly define
+  // a function. This avoids accidentally defining the function within a tag
+  // declaration, for example.
   Scope *ContextScope = BlockScope;
-  while (!ContextScope->getEntity())
+  while (!ContextScope->getEntity() ||
+         (!ContextScope->getEntity()->isFunctionOrMethod() &&
+          !ContextScope->getEntity()->isTranslationUnit()))
     ContextScope = ContextScope->getParent();
   ContextRAII SavedContext(*this, ContextScope->getEntity());
 

diff  --git a/clang/test/Sema/implicit-decl.c b/clang/test/Sema/implicit-decl.c
index 351f70ea33665..d7d3e108e8048 100644
--- a/clang/test/Sema/implicit-decl.c
+++ b/clang/test/Sema/implicit-decl.c
@@ -1,18 +1,16 @@
-// RUN: %clang_cc1 %s -verify -fsyntax-only -Werror=implicit-function-declaration -std=c99
-// RUN: %clang_cc1 %s -verify -fsyntax-only -std=c11
-// RUN: %clang_cc1 %s -verify=c2x -fsyntax-only -std=c2x
+// RUN: %clang_cc1 %s -verify=expected,both -fsyntax-only -Werror=implicit-function-declaration -std=c99
+// RUN: %clang_cc1 %s -verify=expected,both -fsyntax-only -std=c11
+// RUN: %clang_cc1 %s -verify=c2x,both -fsyntax-only -std=c2x
 
 /// -Werror-implicit-function-declaration is a deprecated alias used by many projects.
-// RUN: %clang_cc1 %s -verify -fsyntax-only -Werror-implicit-function-declaration
+// RUN: %clang_cc1 %s -verify=expected,both -fsyntax-only -Werror-implicit-function-declaration
 
 // c2x-note@*:* {{'__builtin_va_list' declared here}}
 
 typedef int int32_t;
 typedef unsigned char Boolean;
 
-extern int printf(__const char *__restrict __format, ...); // expected-note{{'printf' declared here}} \
-                                                              c2x-note {{'printf' declared here}}
-
+extern int printf(__const char *__restrict __format, ...); // both-note{{'printf' declared here}}
 void func(void) {
    int32_t *vector[16];
    const char compDesc[16 + 1];
@@ -53,3 +51,26 @@ void test_suggestion(void) {
   bork(); // expected-error {{call to undeclared function 'bork'; ISO C99 and later do not support implicit function declarations}} \
              c2x-error {{use of undeclared identifier 'bork'}}
 }
+
+// The following used to cause an assertion from trying to define the implicit
+// function within a structure scope as opposed to within function or global
+// scoped.
+int GH48579_1(void) {
+  struct {
+    int x __attribute__((aligned(({ a(); })))); // expected-error {{call to undeclared function 'a'; ISO C99 and later do not support implicit function declarations}} \
+                                                   c2x-error {{use of undeclared identifier 'a'}} \
+                                                   both-error {{'aligned' attribute requires integer constant}}
+  } x;
+}
+
+void GH48579_2(void) {
+  struct S {
+    int array[({ a(); })]; // expected-error {{call to undeclared function 'a'; ISO C99 and later do not support implicit function declarations}} \
+                              c2x-error {{use of undeclared identifier 'a'}} \
+                              expected-error {{fields must have a constant size: 'variable length array in structure' extension will never be supported}} \
+                              c2x-error {{size of array has non-integer type 'void'}}
+  };
+}
+
+int GH48579_3 = ({a();});              // both-error {{statement expression not allowed at file scope}}
+void GH48579_4(int array[({ a(); })]); // both-error {{statement expression not allowed at file scope}}


        


More information about the cfe-commits mailing list