// RUN: not %clang_cc1 -triple x86_64-unknown-unknown -Wno-unused-value -fcxx-exceptions -std=gnu++17 -frecovery-ast -frecovery-ast-type -ast-dump %s | FileCheck -strict-whitespace %s // RUN: not %clang_cc1 -triple x86_64-unknown-unknown -Wno-unused-value -fcxx-exceptions -std=gnu++17 -fno-recovery-ast -ast-dump %s | FileCheck --check-prefix=DISABLED -strict-whitespace %s int some_func(int *); // CHECK: VarDecl {{.*}} invalid_call // CHECK-NEXT: `-RecoveryExpr {{.*}} 'int' contains-errors // CHECK-NEXT: |-UnresolvedLookupExpr {{.*}} 'some_func' // CHECK-NEXT: `-IntegerLiteral {{.*}} 123 // DISABLED-NOT: -RecoveryExpr {{.*}} contains-errors int invalid_call = some_func(123); void test_invalid_call_1(int s) { // CHECK: CallExpr {{.*}} '' contains-errors // CHECK-NEXT: |-UnresolvedLookupExpr {{.*}} 'some_func' // CHECK-NEXT: |-RecoveryExpr {{.*}} // CHECK-NEXT: `-BinaryOperator {{.*}} // CHECK-NEXT: |-RecoveryExpr {{.*}} // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1 some_func(undef1, undef2+1); // CHECK: BinaryOperator {{.*}} '' contains-errors '=' // CHECK-NEXT: |-DeclRefExpr {{.*}} 's' // CHECK-NEXT: `-CallExpr {{.*}} '' contains-errors // CHECK-NEXT: |-UnresolvedLookupExpr {{.*}} 'some_func' // CHECK-NEXT: `-RecoveryExpr {{.*}} contains-errors s = some_func(undef1); // CHECK: VarDecl {{.*}} var 'int' // CHECK-NEXT: `-CallExpr {{.*}} '' contains-errors // CHECK-NEXT: |-UnresolvedLookupExpr {{.*}} 'some_func' // CHECK-NEXT: `-RecoveryExpr {{.*}} contains-errors int var = some_func(undef1); } int some_func2(int a, int b); void test_invalid_call_2() { // CHECK: -RecoveryExpr {{.*}} 'int' contains-errors // CHECK-NEXT: `-UnresolvedLookupExpr {{.*}} '' lvalue (ADL) = 'some_func2' some_func2(,); // CHECK: -RecoveryExpr {{.*}} 'int' contains-errors // CHECK-NEXT: `-UnresolvedLookupExpr {{.*}} '' lvalue (ADL) = 'some_func2' some_func2(,,); // CHECK: `-RecoveryExpr {{.*}} 'int' contains-errors // CHECK-NEXT: |-UnresolvedLookupExpr {{.*}} '' lvalue (ADL) = 'some_func2' // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1 some_func2(1,); // FIXME: Handle invalid argument with recovery // CHECK-NOT: `-RecoveryExpr some_func2(,1); } int ambig_func(double); int ambig_func(float); // CHECK: VarDecl {{.*}} ambig_call // CHECK-NEXT: `-RecoveryExpr {{.*}} 'int' contains-errors // CHECK-NEXT: |-UnresolvedLookupExpr {{.*}} 'ambig_func' // CHECK-NEXT: `-IntegerLiteral {{.*}} 123 // DISABLED-NOT: -RecoveryExpr {{.*}} contains-errors int ambig_call = ambig_func(123); // CHECK: VarDecl {{.*}} unresolved_call1 // CHECK-NEXT:`-RecoveryExpr {{.*}} '' contains-errors // CHECK-NEXT: `-UnresolvedLookupExpr {{.*}} 'bar' // DISABLED-NOT: -RecoveryExpr {{.*}} contains-errors int unresolved_call1 = bar(); // CHECK: VarDecl {{.*}} unresolved_call2 // CHECK-NEXT:`-CallExpr {{.*}} contains-errors // CHECK-NEXT: |-UnresolvedLookupExpr {{.*}} 'bar' // CHECK-NEXT: |-RecoveryExpr {{.*}} contains-errors // CHECK-NEXT: | `-UnresolvedLookupExpr {{.*}} 'baz' // CHECK-NEXT: `-RecoveryExpr {{.*}} contains-errors // CHECK-NEXT: `-UnresolvedLookupExpr {{.*}} 'qux' // DISABLED-NOT: -RecoveryExpr {{.*}} contains-errors int unresolved_call2 = bar(baz(), qux()); constexpr int a = 10; // CHECK: VarDecl {{.*}} postfix_inc // CHECK-NEXT:`-RecoveryExpr {{.*}} contains-errors // CHECK-NEXT: `-DeclRefExpr {{.*}} 'a' // DISABLED-NOT: -RecoveryExpr {{.*}} contains-errors int postfix_inc = a++; // CHECK: VarDecl {{.*}} prefix_inc // CHECK-NEXT:`-RecoveryExpr {{.*}} contains-errors // CHECK-NEXT: `-DeclRefExpr {{.*}} 'a' // DISABLED-NOT: -RecoveryExpr {{.*}} contains-errors int prefix_inc = ++a; // CHECK: VarDecl {{.*}} unary_address // CHECK-NEXT:`-RecoveryExpr {{.*}} contains-errors // CHECK-NEXT: `-ParenExpr {{.*}} // CHECK-NEXT: `-BinaryOperator {{.*}} '+' // CHECK-NEXT: |-ImplicitCastExpr // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'a' // DISABLED-NOT: -RecoveryExpr {{.*}} contains-errors int unary_address = &(a + 1); // CHECK: VarDecl {{.*}} unary_bitinverse // CHECK-NEXT:`-RecoveryExpr {{.*}} contains-errors // CHECK-NEXT: `-ParenExpr {{.*}} // CHECK-NEXT: `-BinaryOperator {{.*}} '+' // CHECK-NEXT: |-ImplicitCastExpr // CHECK-NEXT: | `-ImplicitCastExpr // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'a' // DISABLED-NOT: -RecoveryExpr {{.*}} contains-errors int unary_bitinverse = ~(a + 0.0); // CHECK: VarDecl {{.*}} binary // CHECK-NEXT:`-RecoveryExpr {{.*}} contains-errors // CHECK-NEXT: |-DeclRefExpr {{.*}} 'a' // CHECK-NEXT: `-CXXNullPtrLiteralExpr // DISABLED-NOT: -RecoveryExpr {{.*}} contains-errors int binary = a + nullptr; // CHECK: VarDecl {{.*}} ternary // CHECK-NEXT:`-RecoveryExpr {{.*}} contains-errors // CHECK-NEXT: |-DeclRefExpr {{.*}} 'a' // CHECK-NEXT: |-CXXNullPtrLiteralExpr // CHECK-NEXT: `-DeclRefExpr {{.*}} 'a' // DISABLED-NOT: -RecoveryExpr {{.*}} contains-errors int ternary = a ? nullptr : a; // CHECK: FunctionDecl // CHECK-NEXT:|-ParmVarDecl {{.*}} x // CHECK-NEXT:`-CompoundStmt // CHECK-NEXT: |-RecoveryExpr {{.*}} contains-errors // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'foo' // CHECK-NEXT: `-CallExpr {{.*}} contains-errors // CHECK-NEXT: |-RecoveryExpr {{.*}} contains-errors // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'foo' // CHECK-NEXT: `-DeclRefExpr {{.*}} 'x' struct Foo {} foo; void test(int x) { foo.abc; foo->func(x); } void AccessIncompleteClass() { struct Forward; Forward* ptr; // CHECK: CallExpr {{.*}} '' // CHECK-NEXT: `-CXXDependentScopeMemberExpr {{.*}} '' // CHECK-NEXT: `-RecoveryExpr {{.*}} '' contains-errors // CHECK-NEXT: `-DeclRefExpr {{.*}} 'Forward *' ptr->method(); } struct Foo2 { double func(); class ForwardClass; ForwardClass createFwd(); int overload(); int overload(int, int); }; void test2(Foo2 f) { // CHECK: RecoveryExpr {{.*}} 'double' // CHECK-NEXT: |-MemberExpr {{.*}} '' // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'f' // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1 f.func(1); // CHECK: RecoveryExpr {{.*}} 'ForwardClass':'Foo2::ForwardClass' // CHECK-NEXT: `-MemberExpr {{.*}} '' .createFwd // CHECK-NEXT: `-DeclRefExpr {{.*}} 'f' f.createFwd(); // CHECK: RecoveryExpr {{.*}} 'int' contains-errors // CHECK-NEXT: |-UnresolvedMemberExpr // CHECK-NEXT: `-DeclRefExpr {{.*}} 'Foo2' // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1 f.overload(1); } // CHECK: |-AlignedAttr {{.*}} alignas // CHECK-NEXT:| `-RecoveryExpr {{.*}} contains-errors // CHECK-NEXT:| `-UnresolvedLookupExpr {{.*}} 'invalid' struct alignas(invalid()) Aligned {}; auto f(); int f(double); // CHECK: VarDecl {{.*}} unknown_type_call 'int' // CHECK-NEXT: `-RecoveryExpr {{.*}} '' int unknown_type_call = f(0, 0); void InvalidInitalizer(int x) { struct Bar { Bar(); }; // CHECK: `-VarDecl {{.*}} a1 'Bar' // CHECK-NEXT: `-RecoveryExpr {{.*}} contains-errors // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1 Bar a1(1); // CHECK: `-VarDecl {{.*}} a2 'Bar' // CHECK-NEXT: `-RecoveryExpr {{.*}} contains-errors // CHECK-NEXT: `-DeclRefExpr {{.*}} 'x' Bar a2(x); // CHECK: `-VarDecl {{.*}} a3 'Bar' // CHECK-NEXT: `-RecoveryExpr {{.*}} contains-errors // CHECK-NEXT: `-InitListExpr // CHECK-NEDT: `-DeclRefExpr {{.*}} 'x' Bar a3{x}; // CHECK: `-VarDecl {{.*}} a4 'Bar' // CHECK-NEXT: `-ParenListExpr {{.*}} 'NULL TYPE' contains-errors // CHECK-NEXT: `-RecoveryExpr {{.*}} contains-errors // CHECK-NEXT: `-UnresolvedLookupExpr {{.*}} 'invalid' Bar a4(invalid()); // CHECK: `-VarDecl {{.*}} a5 'Bar' // CHECK-NEXT: `-InitListExpr {{.*}} contains-errors // CHECK-NEXT: `-RecoveryExpr {{.*}} contains-errors // CHECK-NEXT: `-UnresolvedLookupExpr {{.*}} 'invalid' Bar a5{invalid()}; // CHECK: `-VarDecl {{.*}} b1 'Bar' // CHECK-NEXT: `-RecoveryExpr {{.*}} contains-errors // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1 Bar b1 = 1; // CHECK: `-VarDecl {{.*}} b2 'Bar' // CHECK-NEXT: `-RecoveryExpr {{.*}} contains-errors // CHECK-NEXT: `-InitListExpr Bar b2 = {1}; // CHECK: `-VarDecl {{.*}} b3 'Bar' // CHECK-NEXT: `-RecoveryExpr {{.*}} 'Bar' contains-errors // CHECK-NEXT: `-DeclRefExpr {{.*}} 'x' 'int' Bar b3 = Bar(x); // CHECK: `-VarDecl {{.*}} b4 'Bar' // CHECK-NEXT: `-RecoveryExpr {{.*}} 'Bar' contains-errors // CHECK-NEXT: `-InitListExpr {{.*}} 'void' // CHECK-NEXT: `-DeclRefExpr {{.*}} 'x' 'int' Bar b4 = Bar{x}; // CHECK: `-VarDecl {{.*}} b5 'Bar' // CHECK-NEXT: `-CXXUnresolvedConstructExpr {{.*}} 'Bar' contains-errors 'Bar' // CHECK-NEXT: `-RecoveryExpr {{.*}} contains-errors // CHECK-NEXT: `-UnresolvedLookupExpr {{.*}} 'invalid' Bar b5 = Bar(invalid()); // CHECK: `-VarDecl {{.*}} b6 'Bar' // CHECK-NEXT: `-CXXUnresolvedConstructExpr {{.*}} 'Bar' contains-errors 'Bar' // CHECK-NEXT: `-InitListExpr {{.*}} contains-errors // CHECK-NEXT: `-RecoveryExpr {{.*}} contains-errors // CHECK-NEXT: `-UnresolvedLookupExpr {{.*}} 'invalid' Bar b6 = Bar{invalid()}; // CHECK: RecoveryExpr {{.*}} 'Bar' contains-errors // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1 Bar(1); // CHECK: `-VarDecl {{.*}} var1 // CHECK-NEXT: `-BinaryOperator {{.*}} '' contains-errors // CHECK-NEXT: |-RecoveryExpr {{.*}} '' contains-errors // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1 int var1 = undef + 1; } void InitializerForAuto() { // CHECK: `-VarDecl {{.*}} invalid a 'auto' // CHECK-NEXT: `-RecoveryExpr {{.*}} '' contains-errors // CHECK-NEXT: `-UnresolvedLookupExpr {{.*}} 'invalid' auto a = invalid(); // CHECK: `-VarDecl {{.*}} invalid b 'auto' // CHECK-NEXT: `-CallExpr {{.*}} '' contains-errors // CHECK-NEXT: |-UnresolvedLookupExpr {{.*}} 'some_func' // CHECK-NEXT: `-RecoveryExpr {{.*}} '' contains-errors // CHECK-NEXT: `-UnresolvedLookupExpr {{.*}} 'invalid' auto b = some_func(invalid()); decltype(ned); // very bad initailizer: there is an unresolved typo expr internally, we just // drop it. // CHECK: `-VarDecl {{.*}} invalid unresolved_typo 'auto' auto unresolved_typo = gned.*[] {}; } // Verified that the generated call operator is invalid. // CHECK: |-CXXMethodDecl {{.*}} invalid operator() 'auto () const -> auto' using Escape = decltype([] { return undef(); }()); // CHECK: VarDecl {{.*}} NoCrashOnInvalidInitList // CHECK-NEXT: `-RecoveryExpr {{.*}} '' contains-errors lvalue // CHECK-NEXT: `-InitListExpr // CHECK-NEXT: `-DesignatedInitExpr {{.*}} 'void' // CHECK-NEXT: `-CXXNullPtrLiteralExpr {{.*}} 'std::nullptr_t' struct { int& abc; } NoCrashOnInvalidInitList = { .abc = nullptr, }; // Verify the value category of recovery expression. int prvalue(int); int &lvalue(int); int &&xvalue(int); void ValueCategory() { // CHECK: RecoveryExpr {{.*}} 'int' contains-errors prvalue(); // call to a function (nonreference return type) yields a prvalue (not print by default) // CHECK: RecoveryExpr {{.*}} 'int' contains-errors lvalue lvalue(); // call to a function (lvalue reference return type) yields an lvalue. // CHECK: RecoveryExpr {{.*}} 'int' contains-errors xvalue xvalue(); // call to a function (rvalue reference return type) yields an xvalue. } void InvalidCondition() { // CHECK: IfStmt {{.*}} // CHECK-NEXT: |-RecoveryExpr {{.*}} '' contains-errors // CHECK-NEXT: | `-UnresolvedLookupExpr {{.*}} if (invalid()) {} // CHECK: WhileStmt {{.*}} // CHECK-NEXT: |-RecoveryExpr {{.*}} '' contains-errors // CHECK-NEXT: | `-UnresolvedLookupExpr {{.*}} while (invalid()) {} // CHECK: SwitchStmt {{.*}} // CHECK-NEXT: |-RecoveryExpr {{.*}} '' contains-errors // CHECK-NEXT: | `-UnresolvedLookupExpr {{.*}} switch(invalid()) { case 1: break; } // FIXME: figure out why the type of ConditionalOperator is not int. // CHECK: ConditionalOperator {{.*}} '' contains-errors // CHECK-NEXT: |-RecoveryExpr {{.*}} '' contains-errors // CHECK-NEXT: | `-UnresolvedLookupExpr {{.*}} // CHECK-NEXT: |-IntegerLiteral {{.*}} 'int' 1 // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 2 invalid() ? 1 : 2; } void CtorInitializer() { struct S{int m}; class MemberInit { int x, y, z; S s; MemberInit() : x(invalid), y(invalid, invalid), z(invalid()), s(1,2) {} // CHECK: CXXConstructorDecl {{.*}} MemberInit 'void ()' // CHECK-NEXT: |-CXXCtorInitializer Field {{.*}} 'x' 'int' // CHECK-NEXT: | `-ParenListExpr // CHECK-NEXT: | `-RecoveryExpr {{.*}} '' // CHECK-NEXT: |-CXXCtorInitializer Field {{.*}} 'y' 'int' // CHECK-NEXT: | `-ParenListExpr // CHECK-NEXT: | |-RecoveryExpr {{.*}} '' // CHECK-NEXT: | `-RecoveryExpr {{.*}} '' // CHECK-NEXT: |-CXXCtorInitializer Field {{.*}} 'z' 'int' // CHECK-NEXT: | `-ParenListExpr // CHECK-NEXT: | `-RecoveryExpr {{.*}} '' // CHECK-NEXT: | `-UnresolvedLookupExpr {{.*}} '' // CHECK-NEXT: |-CXXCtorInitializer Field {{.*}} 's' 'S' // CHECK-NEXT: | `-RecoveryExpr {{.*}} 'S' contains-errors // CHECK-NEXT: | |-IntegerLiteral {{.*}} 1 // CHECK-NEXT: | `-IntegerLiteral {{.*}} 2 }; class BaseInit : S { BaseInit(float) : S("no match") {} // CHECK: CXXConstructorDecl {{.*}} BaseInit 'void (float)' // CHECK-NEXT: |-ParmVarDecl // CHECK-NEXT: |-CXXCtorInitializer 'S' // CHECK-NEXT: | `-RecoveryExpr {{.*}} 'S' // CHECK-NEXT: | `-StringLiteral BaseInit(double) : S(invalid) {} // CHECK: CXXConstructorDecl {{.*}} BaseInit 'void (double)' // CHECK-NEXT: |-ParmVarDecl // CHECK-NEXT: |-CXXCtorInitializer 'S' // CHECK-NEXT: | `-ParenListExpr // CHECK-NEXT: | `-RecoveryExpr {{.*}} '' }; class DelegatingInit { DelegatingInit(float) : DelegatingInit("no match") {} // CHECK: CXXConstructorDecl {{.*}} DelegatingInit 'void (float)' // CHECK-NEXT: |-ParmVarDecl // CHECK-NEXT: |-CXXCtorInitializer 'DelegatingInit' // CHECK-NEXT: | `-RecoveryExpr {{.*}} 'DelegatingInit' // CHECK-NEXT: | `-StringLiteral DelegatingInit(double) : DelegatingInit(invalid) {} // CHECK: CXXConstructorDecl {{.*}} DelegatingInit 'void (double)' // CHECK-NEXT: |-ParmVarDecl // CHECK-NEXT: |-CXXCtorInitializer 'DelegatingInit' // CHECK-NEXT: | `-ParenListExpr // CHECK-NEXT: | `-RecoveryExpr {{.*}} '' }; } float *brokenReturn() { // CHECK: FunctionDecl {{.*}} brokenReturn return 42; // CHECK: ReturnStmt // CHECK-NEXT: `-RecoveryExpr {{.*}} 'float *' // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 42 } // Return deduction treats the first, second *and* third differently! auto *brokenDeducedReturn(int *x, float *y, double *z) { // CHECK: FunctionDecl {{.*}} invalid brokenDeducedReturn if (x) return x; // CHECK: ReturnStmt // CHECK-NEXT: `-ImplicitCastExpr {{.*}} // CHECK-NEXT: `-DeclRefExpr {{.*}} 'x' 'int *' if (y) return y; // CHECK: ReturnStmt // CHECK-NEXT: `-RecoveryExpr {{.*}} 'int *' // CHECK-NEXT: `-DeclRefExpr {{.*}} 'y' 'float *' if (z) return z; // CHECK: ReturnStmt // CHECK-NEXT: `-RecoveryExpr {{.*}} 'int *' // CHECK-NEXT: `-DeclRefExpr {{.*}} 'z' 'double *' return x; // Unfortunate: we wrap a valid return in RecoveryExpr. // This is to avoid running deduction again after it failed once. // CHECK: ReturnStmt // CHECK-NEXT: `-RecoveryExpr {{.*}} 'int *' // CHECK-NEXT: `-DeclRefExpr {{.*}} 'x' 'int *' } void returnInitListFromVoid() { // CHECK: FunctionDecl {{.*}} returnInitListFromVoid return {7,8}; // CHECK: ReturnStmt // CHECK-NEXT: `-RecoveryExpr {{.*}} '' // CHECK-NEXT: |-IntegerLiteral {{.*}} 'int' 7 // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 8 } void RecoveryExprForInvalidDecls(Unknown InvalidDecl) { InvalidDecl + 1; // CHECK: BinaryOperator {{.*}} // CHECK-NEXT: |-RecoveryExpr {{.*}} '' // CHECK-NEXT: | | `-DeclRefExpr {{.*}} 'InvalidDecl' 'int' // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1 InvalidDecl(); // CHECK: CallExpr {{.*}} // CHECK-NEXT: `-RecoveryExpr {{.*}} '' } void InitializerOfInvalidDecl() { int ValidDecl; Unkown InvalidDecl = ValidDecl; // CHECK: VarDecl {{.*}} invalid InvalidDecl // CHECK-NEXT: `-RecoveryExpr {{.*}} '' contains-errors // CHECK-NEXT: `-DeclRefExpr {{.*}} 'int' lvalue Var {{.*}} 'ValidDecl' Unknown InvalidDeclWithInvalidInit = Invalid; // CHECK: VarDecl {{.*}} invalid InvalidDeclWithInvalidInit // CHECK-NEXT: `-RecoveryExpr {{.*}} '' contains-errors // CHECK-NOT: `-TypoExpr } void RecoverToAnInvalidDecl() { Unknown* foo; // invalid decl goo; // the typo was correct to the invalid foo. // Verify that RecoveryExpr has an inner DeclRefExpr. // CHECK: RecoveryExpr {{.*}} '' contains-errors lvalue // CHECK-NEXT: `-DeclRefExpr {{.*}} 'foo' 'int *' } void RecoveryToDoWhileStmtCond() { // CHECK: FunctionDecl {{.*}} RecoveryToDoWhileStmtCond // CHECK: `-DoStmt {{.*}} // CHECK-NEXT: |-CompoundStmt {{.*}} // CHECK-NEXT: `-BinaryOperator {{.*}} '' contains-errors '<' // CHECK-NEXT: |-BinaryOperator {{.*}} '' contains-errors '+' // CHECK-NEXT: | |-RecoveryExpr {{.*}} '' contains-errors lvalue // CHECK-NEXT: | `-IntegerLiteral {{.*}} 'int' 1 // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 10 do {} while (some_invalid_val + 1 < 10); } void RecoveryForStmtCond() { // CHECK:FunctionDecl {{.*}} RecoveryForStmtCond // CHECK-NEXT:`-CompoundStmt {{.*}} // CHECK-NEXT: `-ForStmt {{.*}} // CHECK-NEXT: |-DeclStmt {{.*}} // CHECK-NEXT: | `-VarDecl {{.*}} // CHECK-NEXT: | `-IntegerLiteral {{.*}} 'int' 0 // CHECK-NEXT: |-<<>> // CHECK-NEXT: |-RecoveryExpr {{.*}} 'bool' contains-errors // CHECK-NEXT: |-UnaryOperator {{.*}} 'int' lvalue prefix '++' // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'int' lvalue Var {{.*}} 'i' 'int' // CHECK-NEXT: `-CompoundStmt {{.*}} for (int i = 0; i < invalid; ++i) {} } // Fix crash issue https://github.com/llvm/llvm-project/issues/112560. // Make sure clang compiles the following code without crashing: // CHECK:NamespaceDecl {{.*}} GH112560 // CHECK-NEXT: |-CXXRecordDecl {{.*}} referenced union U definition // CHECK-NEXT: | |-DefinitionData {{.*}} // CHECK-NEXT: | | |-DefaultConstructor {{.*}} // CHECK-NEXT: | | |-CopyConstructor {{.*}} // CHECK-NEXT: | | |-MoveConstructor {{.*}} // CHECK-NEXT: | | |-CopyAssignment {{.*}} // CHECK-NEXT: | | |-MoveAssignment {{.*}} // CHECK-NEXT: | | `-Destructor {{.*}} // CHECK-NEXT: | |-CXXRecordDecl {{.*}} implicit union U // CHECK-NEXT: | `-FieldDecl {{.*}} invalid f 'int' // CHECK-NEXT: | `-RecoveryExpr {{.*}} 'int' contains-errors // DISABLED-NOT: -RecoveryExpr {{.*}} contains-errors namespace GH112560 { union U { int f = ; }; // CHECK: FunctionDecl {{.*}} foo 'void ()' // CHECK-NEXT: `-CompoundStmt {{.*}} // CHECK-NEXT: `-DeclStmt {{.*}} // CHECK-NEXT: `-VarDecl {{.*}} g 'U':'GH112560::U' listinit // CHECK-NEXT: `-InitListExpr {{.*}} 'U':'GH112560::U' contains-errors field Field {{.*}} 'f' 'int' // CHECK-NEXT: `-CXXDefaultInitExpr {{.*}} 'int' contains-errors has rewritten init // CHECK-NEXT: `-RecoveryExpr {{.*}} 'int' contains-errors // DISABLED-NOT: -RecoveryExpr {{.*}} contains-errors void foo() { U g{}; } } // namespace GH112560