From 9276143e24b079a90482999db58611a459501473 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Thu, 30 Jun 2016 20:24:30 +0000 Subject: [PATCH] Fix typo-correction crash if a typo occurs within the operand of a function-style cast to a non-dependent type which is then used in an invalid way. We'd lose the "type dependent" bit here, and downstream Sema processing would then discard the expression if it was used in a context where its type rendered it invalid. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@274267 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaExprCXX.cpp | 9 ++++++++- test/Parser/cxx1z-init-statement.cpp | 8 +++++--- test/SemaCXX/return.cpp | 2 +- test/SemaCXX/typo-correction-crash.cpp | 2 ++ 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index ea1de0c642..2cd00f8218 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -1222,7 +1222,14 @@ Sema::ActOnCXXTypeConstructExpr(ParsedType TypeRep, if (!TInfo) TInfo = Context.getTrivialTypeSourceInfo(Ty, SourceLocation()); - return BuildCXXTypeConstructExpr(TInfo, LParenLoc, exprs, RParenLoc); + auto Result = BuildCXXTypeConstructExpr(TInfo, LParenLoc, exprs, RParenLoc); + // Avoid creating a non-type-dependent expression that contains typos. + // Non-type-dependent expressions are liable to be discarded without + // checking for embedded typos. + if (!Result.isInvalid() && Result.get()->isInstantiationDependent() && + !Result.get()->isTypeDependent()) + Result = CorrectDelayedTyposInExpr(Result.get()); + return Result; } /// ActOnCXXTypeConstructExpr - Parse construction of a specified type. diff --git a/test/Parser/cxx1z-init-statement.cpp b/test/Parser/cxx1z-init-statement.cpp index e8621babaa..c118522e8c 100644 --- a/test/Parser/cxx1z-init-statement.cpp +++ b/test/Parser/cxx1z-init-statement.cpp @@ -10,6 +10,7 @@ int f() { if (T(f()), g, h; f()) {} // expected-error {{not yet supported}} if (T f(); f()) {} // expected-error {{not yet supported}} if (T f(), g, h; f()) {} // expected-error {{not yet supported}} + if (T(n) = 0; n) {} // expected-error {{not yet supported}} // init-statement expressions if (T{f()}; f()) {} // expected-error {{not yet supported}} @@ -20,6 +21,7 @@ int f() { if (T(n){g}) {} if (T f()) {} // expected-error {{function type}} if (T f(), g, h) {} // expected-error {{function type}} + if (T(n) = 0) {} // condition expressions if (T(f())) {} @@ -27,9 +29,9 @@ int f() { if (T(f()), g, h) {} // expected-warning 2{{unused}} if (T{f()}, g, h) {} // expected-warning 2{{unused}} - // none of the above - // FIXME: This causes a typo-correction crash, as does "void f() { +T(n)(g); }" - //if (T(n)(g)) {} // expected-err-FIXME {{not a function}} + // none of the above, disambiguated as expression (can't be a declaration) + if (T(n)(g)) {} // expected-error {{undeclared identifier 'n'}} + if (T(n)(int())) {} // expected-error {{undeclared identifier 'n'}} // Likewise for 'switch' switch (int n; n) {} // expected-error {{not yet supported}} diff --git a/test/SemaCXX/return.cpp b/test/SemaCXX/return.cpp index 8c1664516a..db289240d1 100644 --- a/test/SemaCXX/return.cpp +++ b/test/SemaCXX/return.cpp @@ -118,5 +118,5 @@ void cxx_unresolved_expr() { // CXXUnresolvedConstructExpr, and the missing ')' gives it an invalid source // location for its rparen. Check that emitting a diag on the range of the // expr doesn't assert. - return int(undeclared, 4; // expected-error {{expected ')'}} expected-note{{to match this '('}} expected-error {{void function 'cxx_unresolved_expr' should not return a value}} expected-error {{use of undeclared identifier 'undeclared'}} + return int(undeclared, 4; // expected-error {{expected ')'}} expected-note{{to match this '('}} expected-error {{use of undeclared identifier 'undeclared'}} } diff --git a/test/SemaCXX/typo-correction-crash.cpp b/test/SemaCXX/typo-correction-crash.cpp index 6349937ccd..0b8383dbaf 100644 --- a/test/SemaCXX/typo-correction-crash.cpp +++ b/test/SemaCXX/typo-correction-crash.cpp @@ -17,3 +17,5 @@ typedef int type; } struct FooRecord { }; FooRecord::NestedNamespace::type x; // expected-error {{no member named 'NestedNamespace' in 'FooRecord'; did you mean 'BarNamespace::NestedNamespace'?}} + +void cast_expr(int g) { +int(n)(g); } // expected-error {{undeclared identifier 'n'}} -- 2.40.0