Index: clang/lib/Parse/ParseStmt.cpp =================================================================== --- clang/lib/Parse/ParseStmt.cpp +++ clang/lib/Parse/ParseStmt.cpp @@ -163,6 +163,30 @@ }; } +static bool IsUnknownTypedefName(Parser &P) { + if (P.getCurToken().isNot(tok::identifier)) + return false; + + // Handle things like "unknown *bar;" as declaration for better + // diagnostics. Also it leads to creation of invalid declaration + // node in AST for such cases which is good for AST consumers. + switch (P.NextToken().getKind()) { + default: + return false; + case tok::kw___attribute: + case tok::kw_const: + case tok::kw_volatile: + case tok::star: + case tok::identifier: + return !P.getLangOpts().ObjC; + case tok::amp: + case tok::ampamp: + case tok::kw___declspec: + case tok::l_square: + return P.getLangOpts().CPlusPlus; + } +} + StmtResult Parser::ParseStatementOrDeclarationAfterAttributes( StmtVector &Stmts, ParsedStmtContext StmtCtx, SourceLocation *TrailingElseLoc, ParsedAttributes &CXX11Attrs, @@ -236,7 +260,7 @@ (StmtCtx & ParsedStmtContext::AllowDeclarationsInC) != ParsedStmtContext()) && ((GNUAttributeLoc.isValid() && !(HaveAttrs && AllAttrsAreStmtAttrs)) || - isDeclarationStatement())) { + isDeclarationStatement() || IsUnknownTypedefName(*this))) { SourceLocation DeclStart = Tok.getLocation(), DeclEnd; DeclGroupPtrTy Decl; if (GNUAttributeLoc.isValid()) { Index: clang/test/AST/ast-dump-invalid.c =================================================================== --- /dev/null +++ clang/test/AST/ast-dump-invalid.c @@ -0,0 +1,14 @@ +// RUN: not %clang_cc1 -triple x86_64-unknown-unknown -frecovery-ast -fno-recovery-ast-type -ast-dump %s | FileCheck -strict-whitespace %s + +void test1() { + unknown_t a; + // CHECK: VarDecl{{.*}} invalid a 'int' + unknown_t *b; + // CHECK: VarDecl{{.*}} invalid b 'int *' + unknown_t const *c; + // CHECK: VarDecl{{.*}} invalid c 'const int *' + unknown_t volatile *d; + // CHECK: VarDecl{{.*}} invalid d 'volatile int *' + unknown_t __attribute__ ((aligned (16))) f; + // CHECK: VarDecl{{.*}} invalid f 'int' +} Index: clang/test/AST/ast-dump-recovery.c =================================================================== --- clang/test/AST/ast-dump-recovery.c +++ clang/test/AST/ast-dump-recovery.c @@ -98,3 +98,11 @@ // CHECK-NEXT: `-RecoveryExpr {{.*}} '' ext(undef_var); } + +void RecoverToAnInvalidDecl() { + Unknown* foo; // invalid decl + foo; + // Verify that RecoveryExpr has an inner DeclRefExpr. + // CHECK: RecoveryExpr {{.*}} '' contains-errors lvalue + // CHECK-NEXT: `-DeclRefExpr {{.*}} 'foo' 'int *' +} Index: clang/test/Driver/types.c =================================================================== --- clang/test/Driver/types.c +++ clang/test/Driver/types.c @@ -20,5 +20,5 @@ __uint128_t t; } -// CHECK: error: use of undeclared identifier '__int128_t' -// CHECK: error: use of undeclared identifier '__uint128_t' +// CHECK: error: unknown type name '__int128_t' +// CHECK: error: unknown type name '__uint128_t' Index: clang/test/Parser/CompoundStmtScope.c =================================================================== --- clang/test/Parser/CompoundStmtScope.c +++ clang/test/Parser/CompoundStmtScope.c @@ -4,5 +4,5 @@ { typedef float X; } - X Y; // expected-error {{use of undeclared identifier}} + X Y; // expected-error {{unknown type name 'X'}} } Index: clang/test/Parser/opencl-atomics-cl20.cl =================================================================== --- clang/test/Parser/opencl-atomics-cl20.cl +++ clang/test/Parser/opencl-atomics-cl20.cl @@ -17,10 +17,10 @@ atomic_float f; atomic_flag fl; #if !defined(LANG_VER_OK) -// expected-error@-5 {{use of undeclared identifier 'atomic_int'}} -// expected-error@-5 {{use of undeclared identifier 'atomic_uint'}} -// expected-error@-5 {{use of undeclared identifier 'atomic_float'}} -// expected-error@-5 {{use of undeclared identifier 'atomic_flag'}} +// expected-error@-5 {{unknown type name 'atomic_int'}} +// expected-error@-5 {{unknown type name 'atomic_uint'}} +// expected-error@-5 {{unknown type name 'atomic_float'}} +// expected-error@-5 {{unknown type name 'atomic_flag'}} #endif // Optional types @@ -35,28 +35,26 @@ // one of the extensions is not supported. Here we check with // `cl_khr_int64_base_atomics` only. #if !defined(LANG_VER_OK) || !defined(cl_khr_int64_base_atomics) -// expected-error@-11 {{use of undeclared identifier 'atomic_long'}} -// expected-error@-11 {{use of undeclared identifier 'atomic_ulong'}} -// expected-error@-11 {{use of undeclared identifier 'atomic_double'}} -#if defined(LANG_VER_OK) -// expected-error@-15 {{expected ';' after expression}} -// expected-error@-16 {{use of undeclared identifier 'l'}} -// expected-error@-16 {{expected ';' after expression}} -// expected-error@-17 {{use of undeclared identifier 'ul'}} -#endif +// expected-error@-11 {{unknown type name 'atomic_long'}} +// expected-error@-11 {{unknown type name 'atomic_ulong'}} +// expected-error@-11 {{unknown type name 'atomic_double'}} #if !defined(LANG_VER_OK) || defined(__SPIR64__) -// expected-error@-18 {{use of undeclared identifier 'atomic_size_t'}} -// expected-error@-16 {{use of undeclared identifier 'atomic_ptrdiff_t'}} -#if !defined(LANG_VER_OK) -// expected-error@-20 {{use of undeclared identifier 'atomic_intptr_t'}} -// expected-error@-20 {{use of undeclared identifier 'atomic_uintptr_t'}} +// expected-error@-12 {{unknown type name 'atomic_size_t'}} +// expected-error@-12 {{unknown type name 'atomic_intptr_t'}} +#if !defined(LANG_VER_OK) && defined(__SPIR64__) +// expected-error@-14 {{unknown type name 'atomic_intptr_t'; did you mean 'atomic_int'?}} +// expected-note@* {{'atomic_int' declared here}} +// expected-error@-16 {{unknown type name 'atomic_uintptr_t'}} +// expected-error@-16 {{unknown type name 'atomic_ptrdiff_t'}} #else -// expected-error@-24 {{expected ';' after expression}} -// expected-error@-25 {{use of undeclared identifier 's'}} -// expected-error@-25 {{unknown type name 'atomic_intptr_t'; did you mean 'atomic_int'?}} +#if defined(LANG_VER_OK) // expected-note@* {{'atomic_int' declared here}} -// expected-error@-26 {{unknown type name 'atomic_uintptr_t'; did you mean 'atomic_uint'?}} +// expected-error@-20 {{unknown type name 'atomic_uintptr_t'; did you mean 'atomic_uint'?}} // expected-note@* {{'atomic_uint' declared here}} +#else +// expected-error@-23 {{unknown type name 'atomic_uintptr_t'}} +#endif +// expected-error@-24 {{unknown type name 'atomic_ptrdiff_t'}} #endif #endif #endif Index: clang/test/Parser/recovery.c =================================================================== --- clang/test/Parser/recovery.c +++ clang/test/Parser/recovery.c @@ -10,8 +10,8 @@ // Testcase derived from PR2692 static void f (char * (*g) (char **, int), char **p, ...) { char *s; - va_list v; // expected-error {{identifier}} - s = g (p, __builtin_va_arg(v, int)); // expected-error {{identifier}} + va_list v; // expected-error {{unknown type name 'va_list'}} + s = g (p, __builtin_va_arg(v, int)); } @@ -99,3 +99,12 @@ x = VALUE3 // expected-error{{expected ';' after expression}} x = VALUE4(0) // expected-error{{expected ';' after expression}} } + +void test3(void) { + unknown_t a; // expected-error {{unknown type name 'unknown_t'}} + unknown_t *b; // expected-error {{unknown type name 'unknown_t'}} + unknown_t const *c; // expected-error {{unknown type name 'unknown_t'}} + unknown_t volatile *d; // expected-error {{unknown type name 'unknown_t'}} + unknown_t __attribute__ ((aligned (16))) f; // expected-error {{unknown type name 'unknown_t'}} + int g = unknown_t * a; // expected-error {{use of undeclared identifier 'unknown_t'}} +} Index: clang/test/SemaOpenCL/intel-subgroup-avc-ext-types.cl =================================================================== --- clang/test/SemaOpenCL/intel-subgroup-avc-ext-types.cl +++ clang/test/SemaOpenCL/intel-subgroup-avc-ext-types.cl @@ -46,19 +46,19 @@ // expected-error@-14 {{initializing '__private intel_sub_group_avc_ime_single_reference_streamin_t' with an expression of incompatible type '__private char'}} // expected-error@-14 {{initializing '__private intel_sub_group_avc_ime_dual_reference_streamin_t' with an expression of incompatible type 'int'}} #else -// expected-error@-28 {{use of undeclared identifier 'intel_sub_group_avc_mce_payload_t'}} -// expected-error@-28 {{use of undeclared identifier 'intel_sub_group_avc_ime_payload_t'}} -// expected-error@-28 {{use of undeclared identifier 'intel_sub_group_avc_ref_payload_t'}} -// expected-error@-28 {{use of undeclared identifier 'intel_sub_group_avc_sic_payload_t'}} -// expected-error@-28 {{use of undeclared identifier 'intel_sub_group_avc_mce_result_t'}} -// expected-error@-28 {{use of undeclared identifier 'intel_sub_group_avc_ime_result_t'}} -// expected-error@-28 {{use of undeclared identifier 'intel_sub_group_avc_ref_result_t'}} -// expected-error@-28 {{use of undeclared identifier 'intel_sub_group_avc_sic_result_t'}} -// expected-error@-28 {{use of undeclared identifier 'intel_sub_group_avc_ime_result_single_reference_streamout_t'}} -// expected-error@-28 {{use of undeclared identifier 'intel_sub_group_avc_ime_result_dual_reference_streamout_t'}} -// expected-error@-28 {{use of undeclared identifier 'intel_sub_group_avc_ime_dual_reference_streamin_t'}} -// expected-error@-28 {{use of undeclared identifier 'intel_sub_group_avc_ime_single_reference_streamin_t'}} -// expected-error@-28 {{use of undeclared identifier 'intel_sub_group_avc_ime_dual_reference_streamin_t'}} +// expected-error@-28 {{unknown type name 'intel_sub_group_avc_mce_payload_t'}} +// expected-error@-28 {{unknown type name 'intel_sub_group_avc_ime_payload_t'}} +// expected-error@-28 {{unknown type name 'intel_sub_group_avc_ref_payload_t'}} +// expected-error@-28 {{unknown type name 'intel_sub_group_avc_sic_payload_t'}} +// expected-error@-28 {{unknown type name 'intel_sub_group_avc_mce_result_t'}} +// expected-error@-28 {{unknown type name 'intel_sub_group_avc_ime_result_t'}} +// expected-error@-28 {{unknown type name 'intel_sub_group_avc_ref_result_t'}} +// expected-error@-28 {{unknown type name 'intel_sub_group_avc_sic_result_t'}} +// expected-error@-28 {{unknown type name 'intel_sub_group_avc_ime_result_single_reference_streamout_t'}} +// expected-error@-28 {{unknown type name 'intel_sub_group_avc_ime_result_dual_reference_streamout_t'}} +// expected-error@-28 {{unknown type name 'intel_sub_group_avc_ime_dual_reference_streamin_t'}} +// expected-error@-28 {{unknown type name 'intel_sub_group_avc_ime_single_reference_streamin_t'}} +// expected-error@-28 {{unknown type name 'intel_sub_group_avc_ime_dual_reference_streamin_t'}} #endif } @@ -75,13 +75,12 @@ // expected-error@-5 {{initializing '__private intel_sub_group_avc_ref_payload_t' with an expression of incompatible type '__private intel_sub_group_avc_ime_payload_t'}} // expected-error@-3 {{assigning to '__private intel_sub_group_avc_sic_result_t' from incompatible type '__private intel_sub_group_avc_ime_result_t'}} #else -// expected-error@-11 {{use of undeclared identifier 'intel_sub_group_avc_mce_payload_t'}} -// expected-error@-11 {{use of undeclared identifier 'intel_sub_group_avc_mce_payload_t'}} -// expected-error@-11 {{use of undeclared identifier 'intel_sub_group_avc_ime_payload_t'}} -// expected-error@-11 {{use of undeclared identifier 'intel_sub_group_avc_ref_payload_t'}} -// expected-error@-11 {{use of undeclared identifier 'intel_sub_group_avc_sic_result_t'}} -// expected-error@-11 {{use of undeclared identifier 'intel_sub_group_avc_ime_result_t'}} -// expected-error@-11 {{use of undeclared identifier 'result_sic'}} expected-error@-11 {{use of undeclared identifier 'result_ime'}} +// expected-error@-11 {{unknown type name 'intel_sub_group_avc_mce_payload_t'}} +// expected-error@-11 {{unknown type name 'intel_sub_group_avc_mce_payload_t'}} +// expected-error@-11 {{unknown type name 'intel_sub_group_avc_ime_payload_t'}} +// expected-error@-11 {{unknown type name 'intel_sub_group_avc_ref_payload_t'}} +// expected-error@-11 {{unknown type name 'intel_sub_group_avc_sic_result_t'}} +// expected-error@-11 {{unknown type name 'intel_sub_group_avc_ime_result_t'}} #endif } Index: clang/test/SemaOpenCL/invalid-device-enqueue-types-cl3.0.cl =================================================================== --- clang/test/SemaOpenCL/invalid-device-enqueue-types-cl3.0.cl +++ clang/test/SemaOpenCL/invalid-device-enqueue-types-cl3.0.cl @@ -5,8 +5,8 @@ clk_event_t e; queue_t q; #ifndef __opencl_c_device_enqueue -// expected-error@-3 {{use of undeclared identifier 'clk_event_t'}} -// expected-error@-3 {{use of undeclared identifier 'queue_t'}} +// expected-error@-3 {{unknown type name 'clk_event_t'}} +// expected-error@-3 {{unknown type name 'queue_t'}} #else // expected-no-diagnostics #endif Index: clang/test/SemaOpenCL/invalid-pipes-cl1.2.cl =================================================================== --- clang/test/SemaOpenCL/invalid-pipes-cl1.2.cl +++ clang/test/SemaOpenCL/invalid-pipes-cl1.2.cl @@ -26,10 +26,5 @@ #endif void bar(void) { - reserve_id_t r; -#if defined(__OPENCL_C_VERSION__) -// expected-error@-2 {{use of undeclared identifier 'reserve_id_t'}} -#else -// expected-error@-4 {{unknown type name 'reserve_id_t'}} -#endif + reserve_id_t r; // expected-error {{unknown type name 'reserve_id_t'}} }