[PATCH] D72810: [LifetimeAnalysis] Add support for lifetime annotations on functions

Dmitri Gribenko via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Wed Jan 22 09:09:15 PST 2020


gribozavr2 added a comment.

I'd also appreciate if you updated the docs for the changes done in this patch.



================
Comment at: clang/include/clang/AST/LifetimeAttr.h:22
+
+/// This represents an abstract memory location that is used in the lifetime
+/// contract representation.
----------------
"/// An abstract memory location..."

It would also really help to show some examples of the sorts of locations it can express (especially the nested field accesses).


================
Comment at: clang/include/clang/AST/LifetimeAttr.h:24
+/// contract representation.
+class ContractVariable {
+public:
----------------
I feel like the name is too broad, maybe LifetimeContractVariable?


================
Comment at: clang/include/clang/AST/LifetimeAttr.h:31
+
+  ContractVariable(const RecordDecl *RD) : RD(RD), Tag(This) {}
+
----------------
I'd suggest to make the above two constructors into named factories as well. It took me a while to realize that converting a RecordDecl* to ContractVariable actually models a "this" pointer.


================
Comment at: clang/include/clang/AST/LifetimeAttr.h:71
+
+  bool isThisPointer() const { return Tag == This; }
+
----------------
I'd suggest to add all such `is*` methods in this commit, and group them next to each other in the source code.


================
Comment at: clang/include/clang/AST/LifetimeAttr.h:143
+using LifetimeContractSet = std::set<ContractVariable>;
+using LifetimeContractMap = std::map<ContractVariable, LifetimeContractSet>;
+
----------------
These names are not descriptive...


================
Comment at: clang/include/clang/AST/LifetimeAttr.h:146
+namespace process_lifetime_contracts {
+// This function and the callees are have the sole purpose of matching the
+// AST that describes the contracts. We are only interested in identifier names
----------------
I'm sorry, but this comment is missing the most important piece of information -- what this function does.

This comment says "matching the AST that describes the contracts", which does give me a feeling of the compiler component, but I have no idea about how exactly it uses the expression that is passed in, and what happens with the map, and why a SourceRange is returned.


================
Comment at: clang/include/clang/Basic/Attr.td:2897
+  let Subjects = SubjectList<[Function]>; // TODO: HasFunctionProto?
+  let Args = [ExprArgument<"Expr">];
+  let LateParsed = 1;
----------------
I'd suggest to call it something other than "Expr" (to avoid confusion with or shadowing the type name) -- "ContractExpr" maybe?


================
Comment at: clang/include/clang/Basic/DiagnosticSemaKinds.td:3342
+  InGroup<LifetimeAnalysis>, DefaultIgnore;
+def warn_dump_lifetime_contracts : Warning<"%0">, InGroup<LifetimeDumpContracts>, DefaultIgnore;
+
----------------
I think a warning that is a debugging aid is new territory.


================
Comment at: clang/lib/AST/LifetimeAttr.cpp:16
+namespace process_lifetime_contracts {
+// Easier access the attribute's representation.
+
----------------
I don't think this comment adds much.


================
Comment at: clang/lib/AST/LifetimeAttr.cpp:18
+
+static const Expr *ignoreReturnValues(const Expr *E) {
+  const Expr *Original;
----------------
I'm not sure what you mean by "return values".

`ignoreWrapperASTNodes`?


================
Comment at: clang/lib/AST/LifetimeAttr.cpp:55
+    else if (Name == "Static")
+      return LifetimeContractSet{ContractVariable::staticVal()};
+    else if (Name == "Invalid")
----------------
The lifetime paper says it is called "global" now:

> Renamed static to global to reduce confusion with the keyword.

Also, the paper spells these special names in all lowercase letters.


================
Comment at: clang/lib/Sema/SemaDeclAttr.cpp:4532
+  if (ErrorRange.isValid())
+    S.Diag(ErrorRange.getBegin(), diag::warn_unsupported_expression)
+        << ErrorRange;
----------------
I'm assuming higher quality error messages are going to come later? Right now it is a catch-all message that is shown for unsupported expressions, expressions that don't type check, and expressions that will never be supported.


================
Comment at: clang/test/Sema/attr-psets-annotation.cpp:24
+struct PointerTraits {
+  static auto deref(const T &t) -> decltype(*t);
+};
----------------
If this code imitates an existing library, please ignore.

Declaring PointerTraits::deref to be a function and then invoking it and using decltype on the return value seems unnecessarily complex.

You could declare a type alias within PointerTraits instead.

```
template<typename T>
struct PointerTraits {
  using DerefType = decltype(*declvar<T>());
};

template<typename T>
struct PointerTraits<T*> {
  using DerefType = T;
}; // Is this specialization needed? Wouldn't the primary template work?

template<typename T>
struct PointerTraits<T&> {
  using DerefType = T;
};
```

Also, a specialization for rvalue references?

However, I'm not sure if the specialization even for regular references will be used -- the free function deref() strips the reference from T (also strips constness from it!) Due to reference collapse rules, T will never be a reference.


================
Comment at: clang/test/Sema/attr-psets-annotation.cpp:95
+  void f(X **out)
+      [[gsl::post(lifetime(deref(out), {this}))]];
+  // expected-warning at -2 {{Pre { }  Post { *out -> { this }; }}}
----------------
I'm not sure what causes this unqualified call to `deref` to call `gsl::deref` (in a different namespace). Does not seem like ADL would do it, since the type of `out` is also not in `gsl`.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D72810





More information about the cfe-commits mailing list