[clang] Respect the [[clang::unsafe_buffer_usage]] attribute for field and constructor initializers (PR #91991)
Dana Jansens via cfe-commits
cfe-commits at lists.llvm.org
Mon Jun 10 09:53:51 PDT 2024
================
@@ -3328,3 +3300,63 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
}
}
}
+
+void clang::checkUnsafeBufferUsage(const Decl *D,
+ UnsafeBufferUsageHandler &Handler,
+ bool EmitSuggestions) {
+#ifndef NDEBUG
+ Handler.clearDebugNotes();
+#endif
+
+ assert(D);
+
+ SmallVector<Stmt *> Stmts;
+
+ // We do not want to visit a Lambda expression defined inside a method
+ // independently. Instead, it should be visited along with the outer method.
+ // FIXME: do we want to do the same thing for `BlockDecl`s?
+ if (const auto *fd = dyn_cast<CXXMethodDecl>(D)) {
+ if (fd->getParent()->isLambda() && fd->getParent()->isLocalClass())
+ return;
+ }
+
+ // Do not emit fixit suggestions for functions declared in an
+ // extern "C" block.
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
+ for (FunctionDecl *FReDecl : FD->redecls()) {
+ if (FReDecl->isExternC()) {
+ EmitSuggestions = false;
+ break;
+ }
+ }
+
+ Stmts.push_back(FD->getBody());
+
+ if (const auto *ID = dyn_cast<CXXConstructorDecl>(D)) {
+ for (const CXXCtorInitializer *CI : ID->inits()) {
+ Stmts.push_back(CI->getInit());
+ }
+ }
+ }
+
+ if (const auto *FD = dyn_cast<FieldDecl>(D)) {
----------------
danakj wrote:
> In your new test the entire constructor is missing. The class is an aggregate, it has no constructor: https://godbolt.org/z/aa869TKsf - so I hope you'll see the warning whenever you aggregate-initialize an instance of such class. Which may or may not mean that there's still no direct need to warn at the definition of the field.
https://godbolt.org/z/qjqaW3Eze here is an example of the 3 ways to call the aggregate ctor.
```
|-DeclStmt <line:12:5, col:26>
| `-VarDecl <col:5, col:24> col:24 m1 'HoldsUnsafeMembers' callinit
| `-CXXConstructExpr <col:24> 'HoldsUnsafeMembers' 'void () noexcept(false)'
|-DeclStmt <line:13:5, col:35>
| `-VarDecl <col:5, col:34> col:10 m2 'HoldsUnsafeMembers' cinit
| `-CXXTemporaryObjectExpr <col:15, col:34> 'HoldsUnsafeMembers' 'void () noexcept(false)' zeroing
`-DeclStmt <line:14:5, col:35>
`-VarDecl <col:5, col:34> col:10 m3 'HoldsUnsafeMembers' cinit
`-CXXFunctionalCastExpr <col:15, col:34> 'HoldsUnsafeMembers' functional cast to HoldsUnsafeMembers <NoOp>
`-InitListExpr <col:33, col:34> 'HoldsUnsafeMembers'
`-CXXDefaultInitExpr <col:34> 'UnsafeMembers' has rewritten init
`-CXXConstructExpr <line:8:28, col:30> 'UnsafeMembers' 'void (int)' list
`-IntegerLiteral <col:29> 'int' 3
```
We do get a CXXDefaultInitExpr if we construct with `{}` but not otherwise.
https://github.com/llvm/llvm-project/pull/91991
More information about the cfe-commits
mailing list