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;
+};


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to