This is an archive of the discontinued LLVM Phabricator instance.

[clang-tidy] Fix PR#34798 'readability-braces-around-statements breaks statements containing braces.'
Needs ReviewPublic

Authored by f00kat on Feb 7 2020, 4:34 AM.

Details

Summary

In method 'BracesAroundStatementsCheck::checkStmt' the call 'Lexer::makeFileCharRange(line 253)' return different EndSourceLocation for different statements.

CharSourceRange FileRange = Lexer::makeFileCharRange(
      CharSourceRange::getTokenRange(S->getSourceRange()), SM,
      Context->getLangOpts());

For example

class c {};
c test()
{
	if (true)
		return {};
	if (true)
		bool b[2] = { true, true };
}

In case

return {};

FileRange.getEnd() will be ';'
In case

bool b[2] = { true, true };

FileRange.getEnd() will be '\r'

Before call 'findEndLocation' we do this

const auto FREnd = FileRange.getEnd().getLocWithOffset(-1);

so 'findEndLocation' received '}' in the first case and ';' in the second what breaks the logic of 'findEndLocation'.

Diff Detail

Event Timeline

f00kat created this revision.Feb 7 2020, 4:34 AM
aaron.ballman added inline comments.Feb 11 2020, 1:10 AM
clang-tools-extra/clang-tidy/readability/BracesAroundStatementsCheck.cpp
30

Elide the braces.

40

Elide braces

76–77

Is there evidence that this behavior is desired? I have a hunch that this is a bug in Clang -- not all InitListExprs will terminate with a semicolon, such as ones that appear as function arguments, like foo({1, 2, 3});, so I'm surprised to see it included here.

ymandel added inline comments.
clang-tools-extra/clang-tidy/readability/BracesAroundStatementsCheck.cpp
21

Could you change this to llvm::Expected<Kind> tryGetTokenKind(SourceLocation Loc, const SourceManager &SM, const ASTContext *Context). From a readability and performance standpoint, returned parameters are generally better than out parameters.

76–77

On a related note, are you sure the cause of this issue is makeFileCharRange? AFAIK, that does not involve any examination of tokens. It purely (attempts) to map from potentially a mix of expanded locations and file locations to purely file locations (and in the same file for that matter).

ymandel added inline comments.Feb 11 2020, 6:37 AM
clang-tools-extra/clang-tidy/readability/BracesAroundStatementsCheck.cpp
76–77

I believe the issue lies with DeclStmt, not InitListExpr. Specifically, the source range provided by DeclStmt. See https://godbolt.org/z/vVtQZ8. The non-decl statements have an end location on the token before the semi, whereas the decl statements given their end location as the semi.

aaron.ballman added inline comments.Feb 13 2020, 9:35 AM
clang-tools-extra/clang-tidy/readability/BracesAroundStatementsCheck.cpp
76–77

Ah, yeah, that sounds plausible too (the end location should be before the semi in both places). Either way, I think we should be fixing this in the frontend rather than trying to hack around it in clang-tidy checks, if at all possible. This may require undoing hacks done elsewhere, though.