Index: clang/lib/Sema/SemaChecking.cpp =================================================================== --- clang/lib/Sema/SemaChecking.cpp +++ clang/lib/Sema/SemaChecking.cpp @@ -14369,6 +14369,10 @@ 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(E)) return CheckConditionalOperator(S, CO, CC, T); Index: clang/test/Sema/incomplete-decl.c =================================================================== --- clang/test/Sema/incomplete-decl.c +++ clang/test/Sema/incomplete-decl.c @@ -1,5 +1,15 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s - +// RUN: %clang_cc1 -fsyntax-only -x c++ -verify %s +#ifdef __cplusplus +struct x y; // expected-error {{variable has incomplete type 'struct x'}} \ + expected-note {{forward declaration of 'x'}} +void foo() { + (void)(1 ? y : y); +} +struct x{ + int a; +}; +#else struct foo; // expected-note 5 {{forward declaration of 'struct foo'}} void b; // expected-error {{variable has incomplete type 'void'}} @@ -29,3 +39,14 @@ struct bar k; struct bar { int a; }; +struct x y; //expected-note {{forward declaration of 'struct x'}}\ +//expected-note {{forward declaration of 'struct x'}} +void foo() { + (void)(1 ? y : y); // expected-error {{incomplete type 'struct x' where a complete type is required}} \ + expected-error {{incomplete type 'struct x' where a complete type is required}} +} +struct x{ + int a; +}; + +#endif