diff options
| author | Artem Dergachev <artem.dergachev@gmail.com> | 2019-07-01 23:02:14 +0000 |
|---|---|---|
| committer | Artem Dergachev <artem.dergachev@gmail.com> | 2019-07-01 23:02:14 +0000 |
| commit | 512f4838c47c5bab13d8bb0eabc01d64222825ae (patch) | |
| tree | 254edeea96759e115a9e20b02bcae713b432567c /clang/lib/StaticAnalyzer/Checkers | |
| parent | 35fdec1b54c6a8b1ca7bee542836abf29c75a85d (diff) | |
| download | bcm5719-llvm-512f4838c47c5bab13d8bb0eabc01d64222825ae.tar.gz bcm5719-llvm-512f4838c47c5bab13d8bb0eabc01d64222825ae.zip | |
[analyzer] NonnullGlobalConstants: Don't be confused by a _Nonnull attribute.
The NonnullGlobalConstants checker models the rule "it doesn't make sense
to make a constant global pointer and initialize it to null"; it makes sure
that whatever it's initialized with is known to be non-null.
Ironically, annotating the type of the pointer as _Nonnull breaks the checker.
Fix handling of the _Nonnull annotation so that it was instead one more reason
to believe that the value is non-null.
Differential Revision: https://reviews.llvm.org/D63956
llvm-svn: 364869
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers')
| -rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp | 23 |
1 files changed, 15 insertions, 8 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp index dd76fd2f129..43dbe57b843 100644 --- a/clang/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp @@ -106,14 +106,21 @@ bool NonnullGlobalConstantsChecker::isGlobalConstString(SVal V) const { return true; // Look through the typedefs. - while (auto *T = dyn_cast<TypedefType>(Ty)) { - Ty = T->getDecl()->getUnderlyingType(); - - // It is sufficient for any intermediate typedef - // to be classified const. - HasConst = HasConst || Ty.isConstQualified(); - if (isNonnullType(Ty) && HasConst) - return true; + while (const Type *T = Ty.getTypePtr()) { + if (const auto *TT = dyn_cast<TypedefType>(T)) { + Ty = TT->getDecl()->getUnderlyingType(); + // It is sufficient for any intermediate typedef + // to be classified const. + HasConst = HasConst || Ty.isConstQualified(); + if (isNonnullType(Ty) && HasConst) + return true; + } else if (const auto *AT = dyn_cast<AttributedType>(T)) { + if (AT->getAttrKind() == attr::TypeNonNull) + return true; + Ty = AT->getModifiedType(); + } else { + return false; + } } return false; } |

