|
28 | 28 | #include "clang/AST/ExprObjC.h"
|
29 | 29 | #include "clang/AST/ExprOpenMP.h"
|
30 | 30 | #include "clang/AST/NSAPI.h"
|
| 31 | +#include "clang/AST/NonTrivialTypeVisitor.h" |
31 | 32 | #include "clang/AST/OperationKinds.h"
|
32 | 33 | #include "clang/AST/Stmt.h"
|
33 | 34 | #include "clang/AST/TemplateBase.h"
|
@@ -7378,6 +7379,98 @@ static QualType getSizeOfArgType(const Expr *E) {
|
7378 | 7379 | return QualType();
|
7379 | 7380 | }
|
7380 | 7381 |
|
| 7382 | +namespace { |
| 7383 | + |
| 7384 | +struct SearchNonTrivialToInitializeField |
| 7385 | + : DefaultInitializedTypeVisitor<SearchNonTrivialToInitializeField> { |
| 7386 | + using Super = |
| 7387 | + DefaultInitializedTypeVisitor<SearchNonTrivialToInitializeField>; |
| 7388 | + |
| 7389 | + SearchNonTrivialToInitializeField(const Expr *E, Sema &S) : E(E), S(S) {} |
| 7390 | + |
| 7391 | + void visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK, QualType FT, |
| 7392 | + SourceLocation SL) { |
| 7393 | + if (const auto *AT = asDerived().getContext().getAsArrayType(FT)) { |
| 7394 | + asDerived().visitArray(PDIK, AT, SL); |
| 7395 | + return; |
| 7396 | + } |
| 7397 | + |
| 7398 | + Super::visitWithKind(PDIK, FT, SL); |
| 7399 | + } |
| 7400 | + |
| 7401 | + void visitARCStrong(QualType FT, SourceLocation SL) { |
| 7402 | + S.DiagRuntimeBehavior(SL, E, S.PDiag(diag::note_nontrivial_field) << 1); |
| 7403 | + } |
| 7404 | + void visitARCWeak(QualType FT, SourceLocation SL) { |
| 7405 | + S.DiagRuntimeBehavior(SL, E, S.PDiag(diag::note_nontrivial_field) << 1); |
| 7406 | + } |
| 7407 | + void visitStruct(QualType FT, SourceLocation SL) { |
| 7408 | + for (const FieldDecl *FD : FT->castAs<RecordType>()->getDecl()->fields()) |
| 7409 | + visit(FD->getType(), FD->getLocation()); |
| 7410 | + } |
| 7411 | + void visitArray(QualType::PrimitiveDefaultInitializeKind PDIK, |
| 7412 | + const ArrayType *AT, SourceLocation SL) { |
| 7413 | + visit(getContext().getBaseElementType(AT), SL); |
| 7414 | + } |
| 7415 | + void visitTrivial(QualType FT, SourceLocation SL) {} |
| 7416 | + |
| 7417 | + static void diag(QualType RT, const Expr *E, Sema &S) { |
| 7418 | + SearchNonTrivialToInitializeField(E, S).visitStruct(RT, SourceLocation()); |
| 7419 | + } |
| 7420 | + |
| 7421 | + ASTContext &getContext() { return S.getASTContext(); } |
| 7422 | + |
| 7423 | + const Expr *E; |
| 7424 | + Sema &S; |
| 7425 | +}; |
| 7426 | + |
| 7427 | +struct SearchNonTrivialToCopyField |
| 7428 | + : CopiedTypeVisitor<SearchNonTrivialToCopyField, false> { |
| 7429 | + using Super = CopiedTypeVisitor<SearchNonTrivialToCopyField, false>; |
| 7430 | + |
| 7431 | + SearchNonTrivialToCopyField(const Expr *E, Sema &S) : E(E), S(S) {} |
| 7432 | + |
| 7433 | + void visitWithKind(QualType::PrimitiveCopyKind PCK, QualType FT, |
| 7434 | + SourceLocation SL) { |
| 7435 | + if (const auto *AT = asDerived().getContext().getAsArrayType(FT)) { |
| 7436 | + asDerived().visitArray(PCK, AT, SL); |
| 7437 | + return; |
| 7438 | + } |
| 7439 | + |
| 7440 | + Super::visitWithKind(PCK, FT, SL); |
| 7441 | + } |
| 7442 | + |
| 7443 | + void visitARCStrong(QualType FT, SourceLocation SL) { |
| 7444 | + S.DiagRuntimeBehavior(SL, E, S.PDiag(diag::note_nontrivial_field) << 0); |
| 7445 | + } |
| 7446 | + void visitARCWeak(QualType FT, SourceLocation SL) { |
| 7447 | + S.DiagRuntimeBehavior(SL, E, S.PDiag(diag::note_nontrivial_field) << 0); |
| 7448 | + } |
| 7449 | + void visitStruct(QualType FT, SourceLocation SL) { |
| 7450 | + for (const FieldDecl *FD : FT->castAs<RecordType>()->getDecl()->fields()) |
| 7451 | + visit(FD->getType(), FD->getLocation()); |
| 7452 | + } |
| 7453 | + void visitArray(QualType::PrimitiveCopyKind PCK, const ArrayType *AT, |
| 7454 | + SourceLocation SL) { |
| 7455 | + visit(getContext().getBaseElementType(AT), SL); |
| 7456 | + } |
| 7457 | + void preVisit(QualType::PrimitiveCopyKind PCK, QualType FT, |
| 7458 | + SourceLocation SL) {} |
| 7459 | + void visitTrivial(QualType FT, SourceLocation SL) {} |
| 7460 | + void visitVolatileTrivial(QualType FT, SourceLocation SL) {} |
| 7461 | + |
| 7462 | + static void diag(QualType RT, const Expr *E, Sema &S) { |
| 7463 | + SearchNonTrivialToCopyField(E, S).visitStruct(RT, SourceLocation()); |
| 7464 | + } |
| 7465 | + |
| 7466 | + ASTContext &getContext() { return S.getASTContext(); } |
| 7467 | + |
| 7468 | + const Expr *E; |
| 7469 | + Sema &S; |
| 7470 | +}; |
| 7471 | + |
| 7472 | +} |
| 7473 | + |
7381 | 7474 | /// \brief Check for dangerous or invalid arguments to memset().
|
7382 | 7475 | ///
|
7383 | 7476 | /// This issues warnings on known problematic, dangerous or unspecified
|
@@ -7543,7 +7636,23 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call,
|
7543 | 7636 | PDiag(diag::warn_arc_object_memaccess)
|
7544 | 7637 | << ArgIdx << FnName << PointeeTy
|
7545 | 7638 | << Call->getCallee()->getSourceRange());
|
7546 |
| - else |
| 7639 | + else if (const auto *RT = PointeeTy->getAs<RecordType>()) { |
| 7640 | + if ((BId == Builtin::BImemset || BId == Builtin::BIbzero) && |
| 7641 | + RT->getDecl()->isNonTrivialToPrimitiveDefaultInitialize()) { |
| 7642 | + DiagRuntimeBehavior(Dest->getExprLoc(), Dest, |
| 7643 | + PDiag(diag::warn_cstruct_memaccess) |
| 7644 | + << ArgIdx << FnName << PointeeTy << 0); |
| 7645 | + SearchNonTrivialToInitializeField::diag(PointeeTy, Dest, *this); |
| 7646 | + } else if ((BId == Builtin::BImemcpy || BId == Builtin::BImemmove) && |
| 7647 | + RT->getDecl()->isNonTrivialToPrimitiveCopy()) { |
| 7648 | + DiagRuntimeBehavior(Dest->getExprLoc(), Dest, |
| 7649 | + PDiag(diag::warn_cstruct_memaccess) |
| 7650 | + << ArgIdx << FnName << PointeeTy << 1); |
| 7651 | + SearchNonTrivialToCopyField::diag(PointeeTy, Dest, *this); |
| 7652 | + } else { |
| 7653 | + continue; |
| 7654 | + } |
| 7655 | + } else |
7547 | 7656 | continue;
|
7548 | 7657 |
|
7549 | 7658 | DiagRuntimeBehavior(
|
|
0 commit comments