diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-02-05 19:37:40 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-02-05 19:37:40 +0000 |
commit | b3090384227bf61f889b6aaf4230eccaacc85514 (patch) | |
tree | 6d36474d5d489e49c094ba806b8b9a65309592bc | |
parent | 123063377428540752bad91c7fbd536a762e31bd (diff) |
Vendor import of clang release_40 branch r294123:vendor/clang/clang-release_40-r294123
Notes
Notes:
svn path=/vendor/clang/dist/; revision=313291
svn path=/vendor/clang/clang-release_40-r294123/; revision=313292; tag=vendor/clang/clang-release_40-r294123
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 8 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 17 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp | 9 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/MemRegion.cpp | 6 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/RegionStore.cpp | 2 | ||||
-rw-r--r-- | test/Analysis/dispatch-once.m | 7 | ||||
-rw-r--r-- | test/Analysis/null-deref-static.m | 35 | ||||
-rw-r--r-- | test/SemaObjCXX/typo-correction.mm | 15 |
8 files changed, 80 insertions, 19 deletions
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 3de677e37ba2..3afa95f7d1f2 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -7190,14 +7190,6 @@ public: ExprResult TransformBlockExpr(BlockExpr *E) { return Owned(E); } - ExprResult TransformObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { - return Owned(E); - } - - ExprResult TransformObjCIvarRefExpr(ObjCIvarRefExpr *E) { - return Owned(E); - } - ExprResult Transform(Expr *E) { ExprResult Res; while (true) { diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 4388ad34e21b..f8e65a119c3c 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -2932,16 +2932,17 @@ public: ExprResult RebuildObjCIvarRefExpr(Expr *BaseArg, ObjCIvarDecl *Ivar, SourceLocation IvarLoc, bool IsArrow, bool IsFreeIvar) { - // FIXME: We lose track of the IsFreeIvar bit. CXXScopeSpec SS; DeclarationNameInfo NameInfo(Ivar->getDeclName(), IvarLoc); - return getSema().BuildMemberReferenceExpr(BaseArg, BaseArg->getType(), - /*FIXME:*/IvarLoc, IsArrow, - SS, SourceLocation(), - /*FirstQualifierInScope=*/nullptr, - NameInfo, - /*TemplateArgs=*/nullptr, - /*S=*/nullptr); + ExprResult Result = getSema().BuildMemberReferenceExpr( + BaseArg, BaseArg->getType(), + /*FIXME:*/ IvarLoc, IsArrow, SS, SourceLocation(), + /*FirstQualifierInScope=*/nullptr, NameInfo, + /*TemplateArgs=*/nullptr, + /*S=*/nullptr); + if (IsFreeIvar && Result.isUsable()) + cast<ObjCIvarRefExpr>(Result.get())->setIsFreeIvar(IsFreeIvar); + return Result; } /// \brief Build a new Objective-C property reference expression. diff --git a/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp b/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp index 0e0f52af3165..437378e53daa 100644 --- a/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp @@ -94,11 +94,18 @@ void MacOSXAPIChecker::CheckDispatchOnce(CheckerContext &C, const CallExpr *CE, bool SuggestStatic = false; os << "Call to '" << FName << "' uses"; if (const VarRegion *VR = dyn_cast<VarRegion>(RB)) { + const VarDecl *VD = VR->getDecl(); + // FIXME: These should have correct memory space and thus should be filtered + // out earlier. This branch only fires when we're looking from a block, + // which we analyze as a top-level declaration, onto a static local + // in a function that contains the block. + if (VD->isStaticLocal()) + return; // We filtered out globals earlier, so it must be a local variable // or a block variable which is under UnknownSpaceRegion. if (VR != R) os << " memory within"; - if (VR->getDecl()->hasAttr<BlocksAttr>()) + if (VD->hasAttr<BlocksAttr>()) os << " the block variable '"; else os << " the local variable '"; diff --git a/lib/StaticAnalyzer/Core/MemRegion.cpp b/lib/StaticAnalyzer/Core/MemRegion.cpp index c4ba2ae199f8..d6e8fe5b51b3 100644 --- a/lib/StaticAnalyzer/Core/MemRegion.cpp +++ b/lib/StaticAnalyzer/Core/MemRegion.cpp @@ -816,9 +816,11 @@ const VarRegion* MemRegionManager::getVarRegion(const VarDecl *D, const StackFrameContext *STC = V.get<const StackFrameContext*>(); - if (!STC) + if (!STC) { + // FIXME: Assign a more sensible memory space to static locals + // we see from within blocks that we analyze as top-level declarations. sReg = getUnknownRegion(); - else { + } else { if (D->hasLocalStorage()) { sReg = isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D) ? static_cast<const MemRegion*>(getStackArgumentsRegion(STC)) diff --git a/lib/StaticAnalyzer/Core/RegionStore.cpp b/lib/StaticAnalyzer/Core/RegionStore.cpp index 15ca2c14f944..934cc5cd3ac4 100644 --- a/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -1849,6 +1849,8 @@ SVal RegionStoreManager::getBindingForVar(RegionBindingsConstRef B, // Function-scoped static variables are default-initialized to 0; if they // have an initializer, it would have been processed by now. + // FIXME: This is only true when we're starting analysis from main(). + // We're losing a lot of coverage here. if (isa<StaticGlobalSpaceRegion>(MS)) return svalBuilder.makeZeroVal(T); diff --git a/test/Analysis/dispatch-once.m b/test/Analysis/dispatch-once.m index 7d54147aebe2..2f82718663e5 100644 --- a/test/Analysis/dispatch-once.m +++ b/test/Analysis/dispatch-once.m @@ -107,3 +107,10 @@ void test_block_var_from_outside_block() { }; dispatch_once(&once, ^{}); // expected-warning{{Call to 'dispatch_once' uses the block variable 'once' for the predicate value.}} } + +void test_static_var_from_outside_block() { + static dispatch_once_t once; + ^{ + dispatch_once(&once, ^{}); // no-warning + }; +} diff --git a/test/Analysis/null-deref-static.m b/test/Analysis/null-deref-static.m new file mode 100644 index 000000000000..887bea252390 --- /dev/null +++ b/test/Analysis/null-deref-static.m @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -w -fblocks -analyze -analyzer-checker=core,deadcode,alpha.core,debug.ExprInspection -verify %s + +void *malloc(unsigned long); +void clang_analyzer_warnIfReached(); + +void test_static_from_block() { + static int *x; + ^{ + *x; // no-warning + }; +} + +void test_static_within_block() { + ^{ + static int *x; + *x; // expected-warning{{Dereference of null pointer}} + }; +} + +void test_static_control_flow(int y) { + static int *x; + if (x) { + // FIXME: Should be reachable. + clang_analyzer_warnIfReached(); // no-warning + } + if (y) { + // We are not sure if this branch is possible, because the developer + // may argue that function is always called with y == 1 for the first time. + // In this case, we can only advise the developer to add assertions + // for suppressing such path. + *x; // expected-warning{{Dereference of null pointer}} + } else { + x = malloc(1); + } +} diff --git a/test/SemaObjCXX/typo-correction.mm b/test/SemaObjCXX/typo-correction.mm index a34a7901e8ee..5e33bfb8cbf0 100644 --- a/test/SemaObjCXX/typo-correction.mm +++ b/test/SemaObjCXX/typo-correction.mm @@ -21,3 +21,18 @@ public: self.m_prop2 = new ClassB(m_prop1); // expected-error {{use of undeclared identifier 'm_prop1'; did you mean '_m_prop1'?}} } @end + +// rdar://30310772 + +@interface InvalidNameInIvarAndPropertyBase +{ +@public + float _a; +} +@property float _b; +@end + +void invalidNameInIvarAndPropertyBase() { + float a = ((InvalidNameInIvarAndPropertyBase*)node)->_a; // expected-error {{use of undeclared identifier 'node'}} + float b = ((InvalidNameInIvarAndPropertyBase*)node)._b; // expected-error {{use of undeclared identifier 'node'}} +} |