Issue 177802
Summary [LifetimeSafety] False-negative for non-trivially view types
Labels false-negative, clang:temporal-safety
Assignees
Reporter usx95
    No error in both the following cases:
```cpp
#include <string>

struct [[gsl::Pointer]] View {
    View(const std::string&);
    ~View();  // Forces a CXXBindTemporaryExpr.
};

View foo(std::string a) { 
    return View(a);
}

View bar(std::string a) {
    View b = View(a);
    return b;
}
```
https://godbolt.org/z/GojcnrKEs
We did some work on the loans to temporaries but missed to handle `CXXBindTemporaryExpr` and `MaterializeTemporaryExpr` for propagating the view's origins.

AST:
```
TranslationUnitDecl
|-CXXRecordDecl <line:3:1, line:6:1> line:3:25 referenced struct View definition
| |-DefinitionData empty standard_layout has_user_declared_ctor can_const_default_init
| | |-DefaultConstructor defaulted_is_constexpr
| | |-CopyConstructor simple trivial has_const_param implicit_has_const_param
| | |-MoveConstructor
| | |-CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
| | |-MoveAssignment
| | `-Destructor non_trivial user_declared
| |-PointerAttr <col:10, col:15>
| |-CXXRecordDecl <col:1, col:25> col:25 implicit referenced struct View
| |-CXXConstructorDecl <line:4:5, col:28> col:5 used View 'void (const std::string &)'
| | `-ParmVarDecl <col:10, col:27> col:28 'const std::string &'
| |-CXXDestructorDecl <line:5:5, col:11> col:5 used ~View 'void () noexcept'
| `-CXXConstructorDecl <line:3:25> col:25 implicit used constexpr View 'void (const View &) noexcept' inline default trivial
|   |-ParmVarDecl <col:25> col:25 'const View &'
|   `-CompoundStmt <col:25>
|-FunctionDecl <line:8:1, line:10:1> line:8:6 foo 'View (std::string)'
| |-ParmVarDecl <col:10, col:22> col:22 used a 'std::string':'std::basic_string<char>' destroyed
| `-CompoundStmt <col:25, line:10:1>
|   `-ReturnStmt <line:9:5, col:18>
| `-ExprWithCleanups <col:12, col:18> 'View'
|       `-CXXFunctionalCastExpr <col:12, col:18> 'View' functional cast to View <ConstructorConversion>
| `-CXXBindTemporaryExpr <col:12, col:18> 'View' (CXXTemporary 0x3f784878)
|           `-CXXConstructExpr <col:12, col:18> 'View' 'void (const std::string &)'
|             `-ImplicitCastExpr <col:17> 'const std::string':'const std::basic_string<char>' lvalue <NoOp>
| `-DeclRefExpr <col:17> 'std::string':'std::basic_string<char>' lvalue ParmVar 0x3f7842c8 'a' 'std::string':'std::basic_string<char>'
`-FunctionDecl <line:12:1, line:15:1> line:12:6 bar 'View (std::string)'
  |-ParmVarDecl <col:10, col:22> col:22 used a 'std::string':'std::basic_string<char>' destroyed
  `-CompoundStmt <col:25, line:15:1>
    |-DeclStmt <line:13:5, col:21>
    | `-VarDecl <col:5, col:20> col:10 used b 'View' nrvo cinit destroyed
    |   `-ExprWithCleanups <col:14, col:20> 'View'
    | `-CXXFunctionalCastExpr <col:14, col:20> 'View' functional cast to View <ConstructorConversion>
    |       `-CXXBindTemporaryExpr <col:14, col:20> 'View' (CXXTemporary 0x3f784bb8)
    |         `-CXXConstructExpr <col:14, col:20> 'View' 'void (const std::string &)'
    | `-ImplicitCastExpr <col:19> 'const std::string':'const std::basic_string<char>' lvalue <NoOp>
    |             `-DeclRefExpr <col:19> 'std::string':'std::basic_string<char>' lvalue ParmVar 0x3f784938 'a' 'std::string':'std::basic_string<char>'
    `-ReturnStmt <line:14:5, col:12> nrvo_candidate(Var 0x3f784ab0 'b' 'View')
      `-CXXConstructExpr <col:12> 'View' 'void (const View &) noexcept'
        `-ImplicitCastExpr <col:12> 'const View' xvalue <NoOp>
          `-DeclRefExpr <col:12> 'View' lvalue Var 0x3f784ab0 'b' 'View'
```

Facts:
```


==========================================
 Lifetime Analysis Facts:
==========================================
Function: bar
  Block B2:
  End of Block
  Block B1:
    Issue (0 (Path: a), ToOrigin: 0 (Expr: DeclRefExpr, Decl: a))
    OriginFlow: 
	Dest: 1 (Expr: ImplicitCastExpr, Type : const std::string &)
	Src:  0 (Expr: DeclRefExpr, Decl: a)
 OriginFlow: 
	Dest: 2 (Expr: CXXConstructExpr, Type : View)
	Src:  1 (Expr: ImplicitCastExpr, Type : const std::string &)
    OriginFlow: 
	Dest: 4 (Expr: CXXFunctionalCastExpr, Type : View)
	Src:  3 (Expr: CXXBindTemporaryExpr, Type : View)
    OriginFlow: 
	Dest: 5 (Decl: b, Type : View)
	Src:  4 (Expr: CXXFunctionalCastExpr, Type : View)
    Use (5 (Decl: b, Type : View), Read)
    Issue (1 (Path: b), ToOrigin: 6 (Expr: DeclRefExpr, Decl: b))
    OriginFlow: 
	Dest: 7 (Expr: ImplicitCastExpr, Type : const View &)
	Src:  6 (Expr: DeclRefExpr, Decl: b)
    OriginFlow: 
	Dest: 8 (Expr: ImplicitCastExpr, Type : View)
	Src:  5 (Decl: b, Type : View)
    OriginFlow: 
	Dest: 9 (Expr: CXXConstructExpr, Type : View)
	Src:  8 (Expr: ImplicitCastExpr, Type : View)
    Expire (1 (Path: b))
    Expire (0 (Path: a))
    OriginEscapes (9 (Expr: CXXConstructExpr, Type : View))
  End of Block
  Block B0:
  End of Block
Compiler returned: 0
```
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to