[PATCH] D76696: [AST] Build recovery expressions by default for C++.

Bevin Hansson via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Thu Mar 26 07:33:40 PDT 2020


ebevhan added a comment.

We found an odd case in our downstream fork after this patch landed. We have a diagnostic in `CheckVariableDeclarationType` that checks for automatic variables that are too large for the stack address space, and it chokes on the testcase `Parser/objcxx11-invalid-lambda.cpp`:

  void foo() {  // expected-note {{to match this '{'}}
    int bar;
    auto baz = [
        bar(  // expected-note {{to match this '('}} expected-note {{to match this '('}}
          foo_undeclared() // expected-error{{use of undeclared identifier 'foo_undeclared'}}
        /* ) */
      ] () { };   // expected-error{{expected ')'}}
  }               // expected-error{{expected ')'}} expected-error {{expected ',' or ']'}} expected-error{{expected ';' at end of declaration}} expected-error{{expected '}'}}

When the lambda is parsed, the parsing of the initializer expression of the 'bar' capture fails since the paren is unbalanced, so it will build:

  ParenListExpr 0xc592ce8 'NULL TYPE' contains-errors
  `-RecoveryExpr 0xc592cc0 '<dependent type>' contains-errors lvalue
    `-UnresolvedLookupExpr 0xc592c38 '<overloaded function type>' lvalue (ADL) = 'foo_undeclared' empty

Then, when building the lambda closure type, it will be given an auto member for `bar` with its type deduced to `AutoType 0xc592d40 'auto' dependent`:

  CXXRecordDecl 0xdfeb798 <...> col:14 implicit class definition
  |-DefinitionData lambda pass_in_registers standard_layout trivially_copyable can_const_default_init
  | |-DefaultConstructor
  | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
  | |-MoveConstructor exists simple trivial needs_implicit
  | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
  | |-MoveAssignment
  | `-Destructor simple irrelevant trivial
  |-CXXMethodDecl 0xdfeb8d0 <line:10:8, col:12> line:5:14 operator() 'void () const' inline
  | `-CompoundStmt 0xdfeba20 <line:10:10, col:12>
  |-FieldDecl 0xdfeba58 <line:6:7> col:7 implicit 'auto'
  `-CXXDestructorDecl 0xdfebb08 <line:5:14> col:14 implicit referenced ~ 'void () noexcept' inline default trivial

However, this just means that `baz` has a very odd type; it's a variable of closure type that contains a dependent member that will never be resolved. Our diagnostic breaks, since the variable's type isn't dependent, but it has a member which is, and we can't take the size of that.

Is the lambda parser really supposed to build this kind of odd type when faced with RecoveryExpr?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D76696/new/

https://reviews.llvm.org/D76696





More information about the cfe-commits mailing list