diff options
author | Manuel Klimek <klimek@google.com> | 2015-03-03 14:54:25 +0000 |
---|---|---|
committer | Manuel Klimek <klimek@google.com> | 2015-03-03 14:54:25 +0000 |
commit | 27ee25f73856ffa904d87f0fe1b49ae934e6b4bb (patch) | |
tree | 2b4016b96e7e0d46945cb0adeb271c1d65adfaf8 /clang/lib/Analysis/UninitializedValues.cpp | |
parent | 2d293400950ac0c72c18d31e54f70716830b6e67 (diff) | |
download | llvm-27ee25f73856ffa904d87f0fe1b49ae934e6b4bb.zip llvm-27ee25f73856ffa904d87f0fe1b49ae934e6b4bb.tar.gz llvm-27ee25f73856ffa904d87f0fe1b49ae934e6b4bb.tar.bz2 |
Make -Wuninitialized warn on pointer-to-member and comma operators.
`isTrackedVar` has been updated to also track records.
`DeclRefExpr`s appearing on the left side of a comma operator are
ignored, while those appearing on the right side are classified as
`Use`.
Patch by Enrico Pertoso.
llvm-svn: 231068
Diffstat (limited to 'clang/lib/Analysis/UninitializedValues.cpp')
-rw-r--r-- | clang/lib/Analysis/UninitializedValues.cpp | 55 |
1 files changed, 44 insertions, 11 deletions
diff --git a/clang/lib/Analysis/UninitializedValues.cpp b/clang/lib/Analysis/UninitializedValues.cpp index 61a2592..8a6870f 100644 --- a/clang/lib/Analysis/UninitializedValues.cpp +++ b/clang/lib/Analysis/UninitializedValues.cpp @@ -14,6 +14,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/StmtVisitor.h" #include "clang/Analysis/Analyses/PostOrderCFGView.h" #include "clang/Analysis/Analyses/UninitializedValues.h" @@ -37,7 +38,7 @@ static bool isTrackedVar(const VarDecl *vd, const DeclContext *dc) { !vd->isExceptionVariable() && !vd->isInitCapture() && vd->getDeclContext() == dc) { QualType ty = vd->getType(); - return ty->isScalarType() || ty->isVectorType(); + return ty->isScalarType() || ty->isVectorType() || ty->isRecordType(); } return false; } @@ -347,6 +348,7 @@ public: } static const DeclRefExpr *getSelfInitExpr(VarDecl *VD) { + if (VD->getType()->isRecordType()) return nullptr; if (Expr *Init = VD->getInit()) { const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(stripCasts(VD->getASTContext(), Init)); @@ -376,10 +378,26 @@ void ClassifyRefs::classify(const Expr *E, Class C) { return; } + if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) { + if (VarDecl *VD = dyn_cast<VarDecl>(ME->getMemberDecl())) { + if (!VD->isStaticDataMember()) + classify(ME->getBase(), C); + } + return; + } + if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) { - if (BO->getOpcode() == BO_Comma) + switch (BO->getOpcode()) { + case BO_PtrMemD: + case BO_PtrMemI: + classify(BO->getLHS(), C); + return; + case BO_Comma: classify(BO->getRHS(), C); - return; + return; + default: + return; + } } FindVarResult Var = findVar(E, DC); @@ -404,7 +422,7 @@ void ClassifyRefs::VisitBinaryOperator(BinaryOperator *BO) { // use. if (BO->isCompoundAssignmentOp()) classify(BO->getLHS(), Use); - else if (BO->getOpcode() == BO_Assign) + else if (BO->getOpcode() == BO_Assign || BO->getOpcode() == BO_Comma) classify(BO->getLHS(), Ignore); } @@ -415,25 +433,40 @@ void ClassifyRefs::VisitUnaryOperator(UnaryOperator *UO) { classify(UO->getSubExpr(), Use); } +static bool isPointerToConst(const QualType &QT) { + return QT->isAnyPointerType() && QT->getPointeeType().isConstQualified(); +} + void ClassifyRefs::VisitCallExpr(CallExpr *CE) { // Classify arguments to std::move as used. if (CE->getNumArgs() == 1) { if (FunctionDecl *FD = CE->getDirectCallee()) { if (FD->isInStdNamespace() && FD->getIdentifier() && FD->getIdentifier()->isStr("move")) { - classify(CE->getArg(0), Use); + // RecordTypes are handled in SemaDeclCXX.cpp. + if (!CE->getArg(0)->getType()->isRecordType()) + classify(CE->getArg(0), Use); return; } } } - // If a value is passed by const reference to a function, we should not assume - // that it is initialized by the call, and we conservatively do not assume - // that it is used. + // If a value is passed by const pointer or by const reference to a function, + // we should not assume that it is initialized by the call, and we + // conservatively do not assume that it is used. for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end(); - I != E; ++I) - if ((*I)->getType().isConstQualified() && (*I)->isGLValue()) - classify(*I, Ignore); + I != E; ++I) { + if ((*I)->isGLValue()) { + if ((*I)->getType().isConstQualified()) + classify((*I), Ignore); + } else if (isPointerToConst((*I)->getType())) { + const Expr *Ex = stripCasts(DC->getParentASTContext(), *I); + const UnaryOperator *UO = dyn_cast<UnaryOperator>(Ex); + if (UO && UO->getOpcode() == UO_AddrOf) + Ex = UO->getSubExpr(); + classify(Ex, Ignore); + } + } } void ClassifyRefs::VisitCastExpr(CastExpr *CE) { |