Hi,
I want to write a check that tests whether a catch is done by const reference or not. I currently have the following code but it can’t distinguish between const reference and reference:
const auto *catchStmt = Result.Nodes.getNodeAs<CXXCatchStmt>("catch");
if (catchStmt != nullptr) {
auto caughtType = catchStmt->getCaughtType();
auto *type = caughtType.getTypePtr();
auto *varDecl = catchStmt->getExceptionDecl();
if (type->isPointerType()) {
diag(varDecl->getLocStart(),
"catch by const reference instead of pointer");
} else if (!type->isReferenceType()) {
diag(varDecl->getLocStart(), "catch by const reference");
} else {
if (caughtType.isConstQualified() == false) {
diag(varDecl->getLocStart(),
"catch by const reference to avoid unnecessary copies");
}
}
}
I tried looking at the varDecl but from there I can’t even find out how to get the QualType. Can somebody give me a hint?
Regards
Tobias
Hi,
I want to write a check that tests whether a catch is done by const reference or not. I currently have the following code but it can’t distinguish between const reference and reference:
const auto *catchStmt = Result.Nodes.getNodeAs<CXXCatchStmt>("catch");
if (catchStmt != nullptr) {
auto caughtType = catchStmt->getCaughtType();
This returns the QualType you are looking for.
caughType.isConstant() && caughtType->isLValueReferenceType();
should tell you if it's a const-qualified lvalue reference type.
~Aaron
Hi,
I want to write a check that tests whether a catch is done by const reference or not. I currently have the following code but it can’t distinguish between const reference and reference:
const auto *catchStmt = Result.Nodes.getNodeAs(“catch”);
if (catchStmt != nullptr) {
auto caughtType = catchStmt->getCaughtType();
This returns the QualType you are looking for.
caughType.isConstant() && caughtType->isLValueReferenceType();
should tell you if it’s a const-qualified lvalue reference type.
~Aaron
This gives me the same result as using QualType::isConstQualified() (see below). Both my examples are detected as not being caught by const reference:
void catchByReference() {
try {
testThrowFunc();
} catch (logic_error &e) {
}
}
void catchByConstReference() {
try {
testThrowFunc();
} catch (const logic_error &e) {
}
}
giving this result:
/Users/tobias/Documents/Development/git/llvm/build/ninja-debug/…/…/llvm/tools/clang/tools/extra/test/clang-tidy/misc-throw-by-value-catch-by-reference.cpp:44:12: warning: catch by const reference to avoid unnecessary copies [misc-throw-by-value-catch-by-reference]
} catch (logic_error &e) {
^
/Users/tobias/Documents/Development/git/llvm/build/ninja-debug/…/…/llvm/tools/clang/tools/extra/test/clang-tidy/misc-throw-by-value-catch-by-reference.cpp:51:12: warning: catch by const reference to avoid unnecessary copies [misc-throw-by-value-catch-by-reference]
} catch (const logic_error &e) {
so for both caughtTypes of these catch statements, neither isConstant() nor isConstQualified() returns true.
Regards
Tobias
Hi,
I want to write a check that tests whether a catch is done by const
reference or not. I currently have the following code but it can’t
distinguish between const reference and reference:
const auto *catchStmt = Result.Nodes.getNodeAs<CXXCatchStmt>("catch");
if (catchStmt != nullptr) {
auto caughtType = catchStmt->getCaughtType();
This returns the QualType you are looking for.
caughType.isConstant() && caughtType->isLValueReferenceType();
should tell you if it's a const-qualified lvalue reference type.
~Aaron
This gives me the same result as using QualType::isConstQualified() (see
below). Both my examples are detected as not being caught by const
reference:
void catchByReference() {
try {
testThrowFunc();
} catch (logic_error &e) {
}
}
void catchByConstReference() {
try {
testThrowFunc();
} catch (const logic_error &e) {
}
}
giving this result:
/Users/tobias/Documents/Development/git/llvm/build/ninja-debug/../../llvm/tools/clang/tools/extra/test/clang-tidy/misc-throw-by-value-catch-by-reference.cpp:44:12:
warning: catch by const reference to avoid unnecessary copies
[misc-throw-by-value-catch-by-reference]
} catch (logic_error &e) {
^
/Users/tobias/Documents/Development/git/llvm/build/ninja-debug/../../llvm/tools/clang/tools/extra/test/clang-tidy/misc-throw-by-value-catch-by-reference.cpp:51:12:
warning: catch by const reference to avoid unnecessary copies
[misc-throw-by-value-catch-by-reference]
} catch (const logic_error &e) {
so for both caughtTypes of these catch statements, neither isConstant() nor
isConstQualified() returns true.
Do you get the same results if you look at the canonical type instead?
auto QT = caughtType->getCaughtType().getCanonicalType();
if (QT.isConstQualified() && QT->isLValueReferenceType()) ...
~Aaron
yes, the result is the same. If someone wants a compilable example: https://github.com/iso8859-1/clang-tools-extra/tree/tobias-additional-checks (a reasonably new fork of the extra tools). The branch “tobias-additional-checks” contains the code.
Thank you
Tobias
Sorry, I got distracted by some clang-query crashes when trying to
make a matcher for this.
The issue is that the top level is not
const qualified. You need to look at what the lvalue reference is
referencing to see if that is const qualified.
clang-query> match
catchStmt(has(varDecl(hasType(references(isConstQualified())))))
Match #1:
E:\Aaron Ballman\Documents\test.cpp:15:5: note: "root" binds here
} catch (const logic_error &e) {
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 match.
~Aaron