[PATCH] D11328: [clang-tidy] new "throw-by-value-catch-by-reference" check for clang-tidy

Tobias Langner via cfe-commits cfe-commits at lists.llvm.org
Fri Oct 9 12:31:12 PDT 2015


Hi Aaron,

> 
>> - the second thing is this MaterializeTemporary advice that you gave. I don’t fully understand it (possibly due to a lack of understanding the AST and a lack of documentation of the proposed methods). Could you please flesh out your idea and why you think it is necessary? Or at least give an example where the current code does not work correctly.
> 
> 
> Consider code like:
> 
>  struct S {};
> 
>  S& g();
>  S h();
> 
>  void f() {
>    throw g(); // Should diagnose, does not currently
>    throw h(); // Should not diagnose, does not currently
>  }
> 
> "throw g();" isn't throwing a temporary because it's throwing from an lvalue reference object (so the user may have a catch clause expecting the caught object to be the same lvalue reference as what g() returns, except that's not actually the case). If you instead check to see whether the throw expression requires a temporary to be materialized, you'll find that g() will diagnose, while h() still will not.
> 
> Does that help?
> 
yes. I added this to the test (you can find it here if required: https://github.com/iso8859-1/clang-tools-extra/blob/tobias-additional-checks/test/clang-tidy/misc-throw-by-value-catch-by-reference.cpp) and ran it through clang-query to check all throw statements. I found the following patterns:

Throw variants
y   throw->new = pointer from new
y/n throw->ImplicitCast->declrefexpr = throw named variable
n   throw->CXXConstructExpr (non-copy-constructor) = construction with normal parameter
n   throw->ImplicitCast->StringLiteral = throw string literal
n   throw->CXXConstructExpr (copy/move)->CallExpr (xvalue) = move
n   throw->CXXConstructExpr (copy/move)->MaterializeTemporary (xvalue)->Call
y   throw->CXXConstructExpr (copy/move)->ImplicitCast->CallExpr (lvalue)
n   throw->CXXConstructExpr (copy/move)->MaterializeTemporary (xvalue)->Call

the y or n or y/n means that we need to diagnose (the y/n depends on whether it’s a function parameter or catch parameter or not). When looking at the section with the copy construction, you’ll see that it depends on lvalue/xvalue (which you probably already knew). But MaterializeTemporary does not detect the T&& case.
My current thought is to go for “isLValue()” on Expr. It can be used for the CallExpr & the MaterializeTemporaryExpr alike and seems to capture the case where we want to diagnose for anonymous temporaries. What do you think?

Tobias



More information about the cfe-commits mailing list