[AST] Preserve the type in RecoveryExprs for broken function calls.
RecoveryExprs are modeled as dependent type to prevent bogus diagnostics
and crashes in clang.
This patch allows to preseve the type for broken calls when the
RecoveryEprs have a known type, e.g. a broken non-overloaded call, a
overloaded call when the all candidates have the same return type, so
that more features (code completion still work on "take2args(x).^") still
work.
However, adding the type is risky, which may result in more clang code being
affected leading to new crashes and hurt diagnostic, and it requires large
effort to minimize the affect (update all sites in clang to handle errorDepend
case), so we add a new flag (off by default) to allow us to develop/test
them incrementally.
This patch also has some trivial fixes to suppress diagnostics (to prevent regressions).
Tested:
all existing tests are passed (when both "-frecovery-ast", "-frecovery-ast-type" flags are flipped on);
Reviewed By: sammccall
Subscribers: rsmith, arphaman, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D79160
2020-05-08 22:13:17 +08:00
|
|
|
// 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
|
[AST] Add RecoveryExpr to retain expressions on semantic errors
Normally clang avoids creating expressions when it encounters semantic
errors, even if the parser knows which expression to produce.
This works well for the compiler. However, this is not ideal for
source-level tools that have to deal with broken code, e.g. clangd is
not able to provide navigation features even for names that compiler
knows how to resolve.
The new RecoveryExpr aims to capture the minimal set of information
useful for the tools that need to deal with incorrect code:
source range of the expression being dropped,
subexpressions of the expression.
We aim to make constructing RecoveryExprs as simple as possible to
ensure writing code to avoid dropping expressions is easy.
Producing RecoveryExprs can result in new code paths being taken in the
frontend. In particular, clang can produce some new diagnostics now and
we aim to suppress bogus ones based on Expr::containsErrors.
We deliberately produce RecoveryExprs only in the parser for now to
minimize the code affected by this patch. Producing RecoveryExprs in
Sema potentially allows to preserve more information (e.g. type of an
expression), but also results in more code being affected. E.g.
SFINAE checks will have to take presence of RecoveryExprs into account.
Initial implementation only works in C++ mode, as it relies on compiler
postponing diagnostics on dependent expressions. C and ObjC often do not
do this, so they require more work to make sure we do not produce too
many bogus diagnostics on the new expressions.
See documentation of RecoveryExpr for more details.
original patch from Ilya
This change is based on https://reviews.llvm.org/D61722
Reviewers: sammccall, rsmith
Reviewed By: sammccall, rsmith
Tags: #clang
Differential Revision: https://reviews.llvm.org/D69330
2020-03-19 23:30:40 +08:00
|
|
|
// 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
|
[AST] Preserve the type in RecoveryExprs for broken function calls.
RecoveryExprs are modeled as dependent type to prevent bogus diagnostics
and crashes in clang.
This patch allows to preseve the type for broken calls when the
RecoveryEprs have a known type, e.g. a broken non-overloaded call, a
overloaded call when the all candidates have the same return type, so
that more features (code completion still work on "take2args(x).^") still
work.
However, adding the type is risky, which may result in more clang code being
affected leading to new crashes and hurt diagnostic, and it requires large
effort to minimize the affect (update all sites in clang to handle errorDepend
case), so we add a new flag (off by default) to allow us to develop/test
them incrementally.
This patch also has some trivial fixes to suppress diagnostics (to prevent regressions).
Tested:
all existing tests are passed (when both "-frecovery-ast", "-frecovery-ast-type" flags are flipped on);
Reviewed By: sammccall
Subscribers: rsmith, arphaman, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D79160
2020-05-08 22:13:17 +08:00
|
|
|
// CHECK-NEXT: `-RecoveryExpr {{.*}} 'int' contains-errors
|
|
|
|
// CHECK-NEXT: |-UnresolvedLookupExpr {{.*}} 'some_func'
|
|
|
|
// CHECK-NEXT: `-IntegerLiteral {{.*}} 123
|
[AST] Add RecoveryExpr to retain expressions on semantic errors
Normally clang avoids creating expressions when it encounters semantic
errors, even if the parser knows which expression to produce.
This works well for the compiler. However, this is not ideal for
source-level tools that have to deal with broken code, e.g. clangd is
not able to provide navigation features even for names that compiler
knows how to resolve.
The new RecoveryExpr aims to capture the minimal set of information
useful for the tools that need to deal with incorrect code:
source range of the expression being dropped,
subexpressions of the expression.
We aim to make constructing RecoveryExprs as simple as possible to
ensure writing code to avoid dropping expressions is easy.
Producing RecoveryExprs can result in new code paths being taken in the
frontend. In particular, clang can produce some new diagnostics now and
we aim to suppress bogus ones based on Expr::containsErrors.
We deliberately produce RecoveryExprs only in the parser for now to
minimize the code affected by this patch. Producing RecoveryExprs in
Sema potentially allows to preserve more information (e.g. type of an
expression), but also results in more code being affected. E.g.
SFINAE checks will have to take presence of RecoveryExprs into account.
Initial implementation only works in C++ mode, as it relies on compiler
postponing diagnostics on dependent expressions. C and ObjC often do not
do this, so they require more work to make sure we do not produce too
many bogus diagnostics on the new expressions.
See documentation of RecoveryExpr for more details.
original patch from Ilya
This change is based on https://reviews.llvm.org/D61722
Reviewers: sammccall, rsmith
Reviewed By: sammccall, rsmith
Tags: #clang
Differential Revision: https://reviews.llvm.org/D69330
2020-03-19 23:30:40 +08:00
|
|
|
// DISABLED-NOT: -RecoveryExpr {{.*}} contains-errors
|
|
|
|
int invalid_call = some_func(123);
|
2020-05-28 19:43:35 +08:00
|
|
|
void test_invalid_call(int s) {
|
|
|
|
// CHECK: CallExpr {{.*}} '<dependent type>' contains-errors
|
|
|
|
// CHECK-NEXT: |-UnresolvedLookupExpr {{.*}} 'some_func'
|
2020-06-02 22:35:29 +08:00
|
|
|
// CHECK-NEXT: |-RecoveryExpr {{.*}} <col:13>
|
|
|
|
// CHECK-NEXT: `-BinaryOperator {{.*}}
|
|
|
|
// CHECK-NEXT: |-RecoveryExpr {{.*}}
|
2020-05-28 19:43:35 +08:00
|
|
|
// CHECK-NEXT: `-IntegerLiteral {{.*}} <col:28> 'int' 1
|
|
|
|
some_func(undef1, undef2+1);
|
|
|
|
|
|
|
|
// CHECK: BinaryOperator {{.*}} '<dependent type>' contains-errors '='
|
|
|
|
// CHECK-NEXT: |-DeclRefExpr {{.*}} 's'
|
|
|
|
// CHECK-NEXT: `-CallExpr {{.*}} '<dependent type>' contains-errors
|
|
|
|
// CHECK-NEXT: |-UnresolvedLookupExpr {{.*}} 'some_func'
|
|
|
|
// CHECK-NEXT: `-RecoveryExpr {{.*}} contains-errors
|
|
|
|
s = some_func(undef1);
|
2020-07-21 15:36:49 +08:00
|
|
|
|
|
|
|
// CHECK: VarDecl {{.*}} var 'int'
|
|
|
|
// CHECK-NEXT: `-CallExpr {{.*}} '<dependent type>' contains-errors
|
|
|
|
// CHECK-NEXT: |-UnresolvedLookupExpr {{.*}} 'some_func'
|
|
|
|
// CHECK-NEXT: `-RecoveryExpr {{.*}} contains-errors
|
2020-05-28 19:43:35 +08:00
|
|
|
int var = some_func(undef1);
|
|
|
|
}
|
[AST] Add RecoveryExpr to retain expressions on semantic errors
Normally clang avoids creating expressions when it encounters semantic
errors, even if the parser knows which expression to produce.
This works well for the compiler. However, this is not ideal for
source-level tools that have to deal with broken code, e.g. clangd is
not able to provide navigation features even for names that compiler
knows how to resolve.
The new RecoveryExpr aims to capture the minimal set of information
useful for the tools that need to deal with incorrect code:
source range of the expression being dropped,
subexpressions of the expression.
We aim to make constructing RecoveryExprs as simple as possible to
ensure writing code to avoid dropping expressions is easy.
Producing RecoveryExprs can result in new code paths being taken in the
frontend. In particular, clang can produce some new diagnostics now and
we aim to suppress bogus ones based on Expr::containsErrors.
We deliberately produce RecoveryExprs only in the parser for now to
minimize the code affected by this patch. Producing RecoveryExprs in
Sema potentially allows to preserve more information (e.g. type of an
expression), but also results in more code being affected. E.g.
SFINAE checks will have to take presence of RecoveryExprs into account.
Initial implementation only works in C++ mode, as it relies on compiler
postponing diagnostics on dependent expressions. C and ObjC often do not
do this, so they require more work to make sure we do not produce too
many bogus diagnostics on the new expressions.
See documentation of RecoveryExpr for more details.
original patch from Ilya
This change is based on https://reviews.llvm.org/D61722
Reviewers: sammccall, rsmith
Reviewed By: sammccall, rsmith
Tags: #clang
Differential Revision: https://reviews.llvm.org/D69330
2020-03-19 23:30:40 +08:00
|
|
|
|
|
|
|
int ambig_func(double);
|
|
|
|
int ambig_func(float);
|
|
|
|
|
|
|
|
// CHECK: VarDecl {{.*}} ambig_call
|
[AST] Preserve the type in RecoveryExprs for broken function calls.
RecoveryExprs are modeled as dependent type to prevent bogus diagnostics
and crashes in clang.
This patch allows to preseve the type for broken calls when the
RecoveryEprs have a known type, e.g. a broken non-overloaded call, a
overloaded call when the all candidates have the same return type, so
that more features (code completion still work on "take2args(x).^") still
work.
However, adding the type is risky, which may result in more clang code being
affected leading to new crashes and hurt diagnostic, and it requires large
effort to minimize the affect (update all sites in clang to handle errorDepend
case), so we add a new flag (off by default) to allow us to develop/test
them incrementally.
This patch also has some trivial fixes to suppress diagnostics (to prevent regressions).
Tested:
all existing tests are passed (when both "-frecovery-ast", "-frecovery-ast-type" flags are flipped on);
Reviewed By: sammccall
Subscribers: rsmith, arphaman, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D79160
2020-05-08 22:13:17 +08:00
|
|
|
// CHECK-NEXT: `-RecoveryExpr {{.*}} 'int' contains-errors
|
|
|
|
// CHECK-NEXT: |-UnresolvedLookupExpr {{.*}} 'ambig_func'
|
|
|
|
// CHECK-NEXT: `-IntegerLiteral {{.*}} 123
|
[AST] Add RecoveryExpr to retain expressions on semantic errors
Normally clang avoids creating expressions when it encounters semantic
errors, even if the parser knows which expression to produce.
This works well for the compiler. However, this is not ideal for
source-level tools that have to deal with broken code, e.g. clangd is
not able to provide navigation features even for names that compiler
knows how to resolve.
The new RecoveryExpr aims to capture the minimal set of information
useful for the tools that need to deal with incorrect code:
source range of the expression being dropped,
subexpressions of the expression.
We aim to make constructing RecoveryExprs as simple as possible to
ensure writing code to avoid dropping expressions is easy.
Producing RecoveryExprs can result in new code paths being taken in the
frontend. In particular, clang can produce some new diagnostics now and
we aim to suppress bogus ones based on Expr::containsErrors.
We deliberately produce RecoveryExprs only in the parser for now to
minimize the code affected by this patch. Producing RecoveryExprs in
Sema potentially allows to preserve more information (e.g. type of an
expression), but also results in more code being affected. E.g.
SFINAE checks will have to take presence of RecoveryExprs into account.
Initial implementation only works in C++ mode, as it relies on compiler
postponing diagnostics on dependent expressions. C and ObjC often do not
do this, so they require more work to make sure we do not produce too
many bogus diagnostics on the new expressions.
See documentation of RecoveryExpr for more details.
original patch from Ilya
This change is based on https://reviews.llvm.org/D61722
Reviewers: sammccall, rsmith
Reviewed By: sammccall, rsmith
Tags: #clang
Differential Revision: https://reviews.llvm.org/D69330
2020-03-19 23:30:40 +08:00
|
|
|
// DISABLED-NOT: -RecoveryExpr {{.*}} contains-errors
|
|
|
|
int ambig_call = ambig_func(123);
|
|
|
|
|
|
|
|
// CHECK: VarDecl {{.*}} unresolved_call1
|
[AST] Preserve the type in RecoveryExprs for broken function calls.
RecoveryExprs are modeled as dependent type to prevent bogus diagnostics
and crashes in clang.
This patch allows to preseve the type for broken calls when the
RecoveryEprs have a known type, e.g. a broken non-overloaded call, a
overloaded call when the all candidates have the same return type, so
that more features (code completion still work on "take2args(x).^") still
work.
However, adding the type is risky, which may result in more clang code being
affected leading to new crashes and hurt diagnostic, and it requires large
effort to minimize the affect (update all sites in clang to handle errorDepend
case), so we add a new flag (off by default) to allow us to develop/test
them incrementally.
This patch also has some trivial fixes to suppress diagnostics (to prevent regressions).
Tested:
all existing tests are passed (when both "-frecovery-ast", "-frecovery-ast-type" flags are flipped on);
Reviewed By: sammccall
Subscribers: rsmith, arphaman, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D79160
2020-05-08 22:13:17 +08:00
|
|
|
// CHECK-NEXT:`-RecoveryExpr {{.*}} '<dependent type>' contains-errors
|
[AST] Add RecoveryExpr to retain expressions on semantic errors
Normally clang avoids creating expressions when it encounters semantic
errors, even if the parser knows which expression to produce.
This works well for the compiler. However, this is not ideal for
source-level tools that have to deal with broken code, e.g. clangd is
not able to provide navigation features even for names that compiler
knows how to resolve.
The new RecoveryExpr aims to capture the minimal set of information
useful for the tools that need to deal with incorrect code:
source range of the expression being dropped,
subexpressions of the expression.
We aim to make constructing RecoveryExprs as simple as possible to
ensure writing code to avoid dropping expressions is easy.
Producing RecoveryExprs can result in new code paths being taken in the
frontend. In particular, clang can produce some new diagnostics now and
we aim to suppress bogus ones based on Expr::containsErrors.
We deliberately produce RecoveryExprs only in the parser for now to
minimize the code affected by this patch. Producing RecoveryExprs in
Sema potentially allows to preserve more information (e.g. type of an
expression), but also results in more code being affected. E.g.
SFINAE checks will have to take presence of RecoveryExprs into account.
Initial implementation only works in C++ mode, as it relies on compiler
postponing diagnostics on dependent expressions. C and ObjC often do not
do this, so they require more work to make sure we do not produce too
many bogus diagnostics on the new expressions.
See documentation of RecoveryExpr for more details.
original patch from Ilya
This change is based on https://reviews.llvm.org/D61722
Reviewers: sammccall, rsmith
Reviewed By: sammccall, rsmith
Tags: #clang
Differential Revision: https://reviews.llvm.org/D69330
2020-03-19 23:30:40 +08:00
|
|
|
// 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;
|
2020-03-25 19:43:53 +08:00
|
|
|
|
|
|
|
// 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);
|
2020-04-13 05:06:00 +08:00
|
|
|
}
|
|
|
|
|
2020-11-30 05:31:42 +08:00
|
|
|
struct Foo2 {
|
|
|
|
double func();
|
|
|
|
class ForwardClass;
|
|
|
|
ForwardClass createFwd();
|
2020-12-14 15:45:13 +08:00
|
|
|
|
|
|
|
int overload();
|
|
|
|
int overload(int, int);
|
2020-11-30 05:31:42 +08:00
|
|
|
};
|
|
|
|
void test2(Foo2 f) {
|
|
|
|
// CHECK: RecoveryExpr {{.*}} 'double'
|
|
|
|
// CHECK-NEXT: |-MemberExpr {{.*}} '<bound member function type>'
|
|
|
|
// CHECK-NEXT: | `-DeclRefExpr {{.*}} 'f'
|
|
|
|
// CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1
|
|
|
|
f.func(1);
|
|
|
|
// CHECK: RecoveryExpr {{.*}} 'Foo2::ForwardClass'
|
|
|
|
// CHECK-NEXT: `-MemberExpr {{.*}} '<bound member function type>' .createFwd
|
|
|
|
// CHECK-NEXT: `-DeclRefExpr {{.*}} 'f'
|
|
|
|
f.createFwd();
|
2020-12-14 15:45:13 +08:00
|
|
|
// CHECK: RecoveryExpr {{.*}} 'int' contains-errors
|
|
|
|
// CHECK-NEXT: |-UnresolvedMemberExpr
|
|
|
|
// CHECK-NEXT: `-DeclRefExpr {{.*}} 'Foo2'
|
|
|
|
// CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1
|
|
|
|
f.overload(1);
|
2020-11-30 05:31:42 +08:00
|
|
|
}
|
|
|
|
|
2020-04-13 05:06:00 +08:00
|
|
|
// CHECK: |-AlignedAttr {{.*}} alignas
|
|
|
|
// CHECK-NEXT:| `-RecoveryExpr {{.*}} contains-errors
|
|
|
|
// CHECK-NEXT:| `-UnresolvedLookupExpr {{.*}} 'invalid'
|
|
|
|
struct alignas(invalid()) Aligned {};
|
2020-04-21 15:57:06 +08:00
|
|
|
|
2020-10-05 18:52:03 +08:00
|
|
|
auto f();
|
|
|
|
int f(double);
|
|
|
|
// CHECK: VarDecl {{.*}} unknown_type_call 'int'
|
|
|
|
// CHECK-NEXT: `-RecoveryExpr {{.*}} '<dependent type>'
|
|
|
|
int unknown_type_call = f(0, 0);
|
|
|
|
|
2020-04-21 15:57:06 +08:00
|
|
|
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};
|
2020-07-20 19:11:15 +08:00
|
|
|
// CHECK: `-VarDecl {{.*}} b3 'Bar'
|
|
|
|
// CHECK-NEXT: `-RecoveryExpr {{.*}} 'Bar' contains-errors
|
|
|
|
// CHECK-NEXT: `-DeclRefExpr {{.*}} 'x' 'int'
|
2020-04-21 15:57:06 +08:00
|
|
|
Bar b3 = Bar(x);
|
2020-07-20 19:11:15 +08:00
|
|
|
// CHECK: `-VarDecl {{.*}} b4 'Bar'
|
|
|
|
// CHECK-NEXT: `-RecoveryExpr {{.*}} 'Bar' contains-errors
|
|
|
|
// CHECK-NEXT: `-InitListExpr {{.*}} 'void'
|
|
|
|
// CHECK-NEXT: `-DeclRefExpr {{.*}} 'x' 'int'
|
2020-04-21 15:57:06 +08:00
|
|
|
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()};
|
2020-07-20 19:11:15 +08:00
|
|
|
|
2020-07-21 15:36:49 +08:00
|
|
|
// CHECK: RecoveryExpr {{.*}} 'Bar' contains-errors
|
2020-07-20 19:11:15 +08:00
|
|
|
// CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1
|
|
|
|
Bar(1);
|
2020-07-21 15:36:49 +08:00
|
|
|
|
|
|
|
// CHECK: `-VarDecl {{.*}} var1
|
|
|
|
// CHECK-NEXT: `-BinaryOperator {{.*}} '<dependent type>' contains-errors
|
|
|
|
// CHECK-NEXT: |-RecoveryExpr {{.*}} '<dependent type>' contains-errors
|
|
|
|
// CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1
|
|
|
|
int var1 = undef + 1;
|
2020-04-21 15:57:06 +08:00
|
|
|
}
|
2020-04-27 16:04:13 +08:00
|
|
|
void InitializerForAuto() {
|
|
|
|
// CHECK: `-VarDecl {{.*}} invalid a 'auto'
|
|
|
|
// CHECK-NEXT: `-RecoveryExpr {{.*}} '<dependent type>' contains-errors
|
|
|
|
// CHECK-NEXT: `-UnresolvedLookupExpr {{.*}} 'invalid'
|
|
|
|
auto a = invalid();
|
|
|
|
|
|
|
|
// CHECK: `-VarDecl {{.*}} invalid b 'auto'
|
|
|
|
// CHECK-NEXT: `-CallExpr {{.*}} '<dependent type>' contains-errors
|
|
|
|
// CHECK-NEXT: |-UnresolvedLookupExpr {{.*}} 'some_func'
|
|
|
|
// CHECK-NEXT: `-RecoveryExpr {{.*}} '<dependent type>' 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.*[] {};
|
|
|
|
}
|
2020-05-18 23:22:59 +08:00
|
|
|
|
2020-05-20 00:05:15 +08:00
|
|
|
// Verified that the generated call operator is invalid.
|
|
|
|
// CHECK: |-CXXMethodDecl {{.*}} invalid operator() 'auto () const -> auto'
|
2020-05-18 23:22:59 +08:00
|
|
|
using Escape = decltype([] { return undef(); }());
|
2020-05-30 05:27:05 +08:00
|
|
|
|
|
|
|
// CHECK: VarDecl {{.*}} NoCrashOnInvalidInitList
|
|
|
|
// CHECK-NEXT: `-RecoveryExpr {{.*}} '<dependent type>' contains-errors lvalue
|
|
|
|
// CHECK-NEXT: `-InitListExpr
|
|
|
|
// CHECK-NEXT: `-DesignatedInitExpr {{.*}} 'void'
|
|
|
|
// CHECK-NEXT: `-CXXNullPtrLiteralExpr {{.*}} 'nullptr_t'
|
|
|
|
struct {
|
|
|
|
int& abc;
|
|
|
|
} NoCrashOnInvalidInitList = {
|
|
|
|
.abc = nullptr,
|
|
|
|
};
|
2020-07-08 19:53:47 +08:00
|
|
|
|
|
|
|
// 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.
|
|
|
|
}
|
2020-07-20 20:53:29 +08:00
|
|
|
|
|
|
|
void InvalidCondition() {
|
|
|
|
// CHECK: IfStmt {{.*}}
|
|
|
|
// CHECK-NEXT: |-RecoveryExpr {{.*}} <col:7, col:15> '<dependent type>' contains-errors
|
|
|
|
// CHECK-NEXT: | `-UnresolvedLookupExpr {{.*}} <col:7>
|
|
|
|
if (invalid()) {}
|
|
|
|
|
|
|
|
// CHECK: WhileStmt {{.*}}
|
|
|
|
// CHECK-NEXT: |-RecoveryExpr {{.*}} <col:10, col:18> '<dependent type>' contains-errors
|
|
|
|
// CHECK-NEXT: | `-UnresolvedLookupExpr {{.*}} <col:10>
|
|
|
|
while (invalid()) {}
|
|
|
|
|
|
|
|
// CHECK: SwitchStmt {{.*}}
|
|
|
|
// CHECK-NEXT: |-RecoveryExpr {{.*}} '<dependent type>' contains-errors
|
|
|
|
// CHECK-NEXT: | `-UnresolvedLookupExpr {{.*}} <col:10>
|
|
|
|
switch(invalid()) {
|
|
|
|
case 1:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// FIXME: figure out why the type of ConditionalOperator is not int.
|
|
|
|
// CHECK: ConditionalOperator {{.*}} '<dependent type>' contains-errors
|
|
|
|
// CHECK-NEXT: |-RecoveryExpr {{.*}} '<dependent type>' contains-errors
|
|
|
|
// CHECK-NEXT: | `-UnresolvedLookupExpr {{.*}}
|
|
|
|
// CHECK-NEXT: |-IntegerLiteral {{.*}} 'int' 1
|
|
|
|
// CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 2
|
|
|
|
invalid() ? 1 : 2;
|
|
|
|
}
|
2020-10-26 19:40:00 +08:00
|
|
|
|
|
|
|
void abcc();
|
|
|
|
void TypoCorrection() {
|
|
|
|
// RecoveryExpr is always dependent-type in this case in order to suppress
|
|
|
|
// following diagnostics.
|
|
|
|
// CHECK: RecoveryExpr {{.*}} '<dependent type>'
|
|
|
|
// CHECK-NEXT: `-CallExpr {{.*}} 'void'
|
|
|
|
// CHECK-NEXT: `-ImplicitCastExpr
|
|
|
|
// CHECK-NEXT: `-DeclRefExpr {{.*}} 'abcc'
|
|
|
|
abc();
|
|
|
|
}
|