[clang] dedd7b6 - Added checking for completeness of lvalue in conditional operator

Aaron Ballman via cfe-commits cfe-commits at lists.llvm.org
Mon Mar 27 11:47:18 PDT 2023


Author: Aditya Singh
Date: 2023-03-27T14:47:08-04:00
New Revision: dedd7b6548f4a37f4f691aa0cd3a709756b7e794

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

LOG: Added checking for completeness of lvalue in conditional operator

Given:
```
struct x y;
int main(void)
{
    (void)(1 ? y : y);
}
struct x {int i;};
```
The conditional operator(?:) requires the second and third operands to
be of compatible types. To be compatible, they also need to be
complete (however, both can be void). Therefore, the expected response
from clang after running the above code as a C program should be error
dialogue pointing out that both the types are incomplete hence
incompatible, but the code compiled without any errors.

The patch ensures the completeness in the CheckCondtionalOperand
function present in llvm-project/clang/lib/Sema/SemaChecking.cpp.

Fixes https://github.com/llvm/llvm-project/issues/59718
Differential Revision: https://reviews.llvm.org/D144358

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/lib/Sema/SemaChecking.cpp
    clang/test/Sema/incomplete-decl.c

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index b2efa99313255..295532a9bfeca 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -186,6 +186,9 @@ Improvements to Clang's diagnostics
   by prioritizing ``-Wunreachable-code-fallthrough``.
 - Clang now correctly diagnoses statement attributes ``[[clang::always_inine]]`` and
   ``[[clang::noinline]]`` when used on a statement with dependent call expressions.
+- Clang now checks for completeness of the second and third arguments in the
+  conditional operator.
+  (`#59718 <https://github.com/llvm/llvm-project/issues/59718>`_)
 
 Bug Fixes in This Version
 -------------------------

diff  --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index a3f2452b53d0c..c8b42519c88dc 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -14396,6 +14396,9 @@ static void CheckConditionalOperator(Sema &S, AbstractConditionalOperator *E,
 static void CheckConditionalOperand(Sema &S, Expr *E, QualType T,
                                     SourceLocation CC, bool &ICContext) {
   E = E->IgnoreParenImpCasts();
+  // Diagnose incomplete type for second or third operand in C.
+  if (!S.getLangOpts().CPlusPlus && E->getType()->isRecordType())
+    S.RequireCompleteExprType(E, diag::err_incomplete_type);
 
   if (auto *CO = dyn_cast<AbstractConditionalOperator>(E))
     return CheckConditionalOperator(S, CO, CC, T);

diff  --git a/clang/test/Sema/incomplete-decl.c b/clang/test/Sema/incomplete-decl.c
index 954d4ab0c672f..bf2890bba9911 100644
--- a/clang/test/Sema/incomplete-decl.c
+++ b/clang/test/Sema/incomplete-decl.c
@@ -1,31 +1,51 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify=c,expected %s
+// RUN: %clang_cc1 -x c++ -fsyntax-only -verify=cxx,expected %s
 
-struct foo; // expected-note 5 {{forward declaration of 'struct foo'}}
+
+
+struct foo; // c-note 5 {{forward declaration of 'struct foo'}} \
+               cxx-note 3 {{forward declaration of 'foo'}}
 
 void b;  // expected-error {{variable has incomplete type 'void'}}
-struct foo f; // expected-error{{tentative definition has type 'struct foo' that is never completed}}
+struct foo f; // c-error {{tentative definition has type 'struct foo' that is never completed}} \
+                 cxx-error {{variable has incomplete type 'struct foo'}}
 
 static void c; // expected-error {{variable has incomplete type 'void'}}
-static struct foo g;  // expected-warning {{tentative definition of variable with internal linkage has incomplete non-array type 'struct foo'}} \
-    expected-error{{tentative definition has type 'struct foo' that is never completed}}
+static struct foo g;  // c-warning {{tentative definition of variable with internal linkage has incomplete non-array type 'struct foo'}} \
+                         c-error {{tentative definition has type 'struct foo' that is never completed}} \
+                         cxx-error {{variable has incomplete type 'struct foo'}}
 
-extern void d;
+extern void d; // cxx-error {{variable has incomplete type 'void'}}
 extern struct foo e;
 
-int ary[]; // expected-warning {{tentative array definition assumed to have one element}}
-struct foo bary[]; // expected-error {{array has incomplete element type 'struct foo'}}
+int ary[]; // c-warning {{tentative array definition assumed to have one element}} \
+              cxx-error {{definition of variable with array type needs an explicit size or an initializer}}
+struct foo bary[]; // c-error {{array has incomplete element type 'struct foo'}} \
+                      cxx-error {{definition of variable with array type needs an explicit size or an initializer}}
 
 void func(void) {
-  int ary[]; // expected-error{{definition of variable with array type needs an explicit size or an initializer}}
+  int ary[]; // expected-error {{definition of variable with array type needs an explicit size or an initializer}}
   void b; // expected-error {{variable has incomplete type 'void'}}
   struct foo f; // expected-error {{variable has incomplete type 'struct foo'}}
 }
 
-int h[]; // expected-warning {{tentative array definition assumed to have one element}}
-int (*i)[] = &h+1; // expected-error {{arithmetic on a pointer to an incomplete type 'int[]'}}
+int h[]; // c-warning {{tentative array definition assumed to have one element}} \
+            cxx-error {{definition of variable with array type needs an explicit size or an initializer}}
+int (*i)[] = &h+1; // c-error {{arithmetic on a pointer to an incomplete type 'int[]'}}
 
 struct bar j = {1}; // expected-error {{variable has incomplete type 'struct bar'}} \
-    expected-note {{forward declaration of 'struct bar'}}
-struct bar k;
+                       c-note {{forward declaration of 'struct bar'}} \
+                       cxx-note 2 {{forward declaration of 'bar'}}
+
+struct bar k; // cxx-error {{variable has incomplete type 'struct bar'}}
 struct bar { int a; };
 
+struct x y; //c-note 2 {{forward declaration of 'struct x'}} \
+              cxx-error {{variable has incomplete type 'struct x'}} \
+              cxx-note {{forward declaration of 'x'}}
+void foo() {
+  (void)(1 ? y : y); // c-error 2 {{incomplete type 'struct x' where a complete type is required}}
+}
+struct x{
+  int a;
+};


        


More information about the cfe-commits mailing list