r364869 - [analyzer] NonnullGlobalConstants: Don't be confused by a _Nonnull attribute.
Artem Dergachev via cfe-commits
cfe-commits at lists.llvm.org
Mon Jul 1 16:02:14 PDT 2019
Author: dergachev
Date: Mon Jul 1 16:02:14 2019
New Revision: 364869
URL: http://llvm.org/viewvc/llvm-project?rev=364869&view=rev
Log:
[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
Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp
cfe/trunk/test/Analysis/nonnull-global-constants.mm
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp?rev=364869&r1=364868&r2=364869&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp Mon Jul 1 16:02:14 2019
@@ -106,14 +106,21 @@ bool NonnullGlobalConstantsChecker::isGl
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;
}
Modified: cfe/trunk/test/Analysis/nonnull-global-constants.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/nonnull-global-constants.mm?rev=364869&r1=364868&r2=364869&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/nonnull-global-constants.mm (original)
+++ cfe/trunk/test/Analysis/nonnull-global-constants.mm Mon Jul 1 16:02:14 2019
@@ -101,3 +101,15 @@ extern CFBooleanRef kBoolMutable;
void testNonnullNonconstBool() {
clang_analyzer_eval(kBoolMutable); // expected-warning{{UNKNOWN}}
}
+
+// If it's annotated as nonnull, it doesn't even need to be const.
+extern CFStringRef _Nonnull str3;
+void testNonnullNonconstCFString() {
+ clang_analyzer_eval(str3); // expected-warning{{TRUE}}
+}
+
+// This one's nonnull for two reasons.
+extern const CFStringRef _Nonnull str4;
+void testNonnullNonnullCFString() {
+ clang_analyzer_eval(str4); // expected-warning{{TRUE}}
+}
More information about the cfe-commits
mailing list