Index: llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h =================================================================== --- llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h +++ llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h @@ -1180,6 +1180,16 @@ /// a specified VarDecl and LocationContext. const VarRegion* getVarRegion(const VarDecl *D, const LocationContext *LC); +private: + /// getMemRegionGloballyStored - Retrieve or create the memory region + /// associated with a specified globally stored, non-static local, VarDecl. + const MemRegion *getMemRegionGloballyStored(const VarDecl *D); + + /// getMemRegionStaticLocal - Retrieve or create the memory region + /// associated with a specified VarDecl and LocationContext. + const MemRegion *getMemRegionStaticLocal(const VarDecl *D, const LocationContext *LC); + +public: /// getVarRegion - Retrieve or create the memory region associated with /// a specified VarDecl and super region. const VarRegion* getVarRegion(const VarDecl *D, const MemRegion *superR); Index: llvm/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp =================================================================== --- llvm/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp +++ llvm/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp @@ -766,87 +766,89 @@ return (const StackFrameContext *)nullptr; } -const VarRegion* MemRegionManager::getVarRegion(const VarDecl *D, - const LocationContext *LC) { - const MemRegion *sReg = nullptr; +const MemRegion* MemRegionManager::getMemRegionGloballyStored(const VarDecl *D) { + assert(D->hasGlobalStorage()); + assert(!D->isStaticLocal()); + // First handle the globals defined in system headers. + if (C.getSourceManager().isInSystemHeader(D->getLocation())) { + // Whitelist the system globals which often DO GET modified, assume the + // rest are immutable. + if (D->getName().find("errno") != StringRef::npos) + return getGlobalsRegion(MemRegion::GlobalSystemSpaceRegionKind); - if (D->hasGlobalStorage() && !D->isStaticLocal()) { + return getGlobalsRegion(MemRegion::GlobalImmutableSpaceRegionKind); + } + // Treat other globals as GlobalInternal unless they are constants. + QualType GQT = D->getType(); + const Type *GT = GQT.getTypePtrOrNull(); + // TODO: We could walk the complex types here and see if everything is + // constified. + if (GT && GQT.isConstQualified() && GT->isArithmeticType()) + return getGlobalsRegion(MemRegion::GlobalImmutableSpaceRegionKind); - // First handle the globals defined in system headers. - if (C.getSourceManager().isInSystemHeader(D->getLocation())) { - // Whitelist the system globals which often DO GET modified, assume the - // rest are immutable. - if (D->getName().find("errno") != StringRef::npos) - sReg = getGlobalsRegion(MemRegion::GlobalSystemSpaceRegionKind); - else - sReg = getGlobalsRegion(MemRegion::GlobalImmutableSpaceRegionKind); + return getGlobalsRegion(); +} - // Treat other globals as GlobalInternal unless they are constants. - } else { - QualType GQT = D->getType(); - const Type *GT = GQT.getTypePtrOrNull(); - // TODO: We could walk the complex types here and see if everything is - // constified. - if (GT && GQT.isConstQualified() && GT->isArithmeticType()) - sReg = getGlobalsRegion(MemRegion::GlobalImmutableSpaceRegionKind); - else - sReg = getGlobalsRegion(); - } +const MemRegion* MemRegionManager::getMemRegionStaticLocal(const VarDecl *D, const LocationContext *LC) { + // FIXME: Once we implement scope handling, we will need to properly lookup + // 'D' to the proper LocationContext. + const DeclContext *DC = D->getDeclContext(); + llvm::PointerUnion V = + getStackOrCaptureRegionForDeclContext(LC, DC, D); - // Finally handle static locals. - } else { - // FIXME: Once we implement scope handling, we will need to properly lookup - // 'D' to the proper LocationContext. - const DeclContext *DC = D->getDeclContext(); - llvm::PointerUnion V = - getStackOrCaptureRegionForDeclContext(LC, DC, D); + if (V.is()) + return V.get(); - if (V.is()) - return V.get(); + const StackFrameContext *STC = V.get(); - const StackFrameContext *STC = V.get(); + if (!STC) + return getUnknownRegion(); - if (!STC) - sReg = getUnknownRegion(); - else { - if (D->hasLocalStorage()) { - sReg = isa(D) || isa(D) - ? static_cast(getStackArgumentsRegion(STC)) - : static_cast(getStackLocalsRegion(STC)); - } - else { - assert(D->isStaticLocal()); - const Decl *STCD = STC->getDecl(); - if (isa(STCD) || isa(STCD)) - sReg = getGlobalsRegion(MemRegion::StaticGlobalSpaceRegionKind, - getFunctionCodeRegion(cast(STCD))); - else if (const BlockDecl *BD = dyn_cast(STCD)) { - // FIXME: The fallback type here is totally bogus -- though it should - // never be queried, it will prevent uniquing with the real - // BlockCodeRegion. Ideally we'd fix the AST so that we always had a - // signature. - QualType T; - if (const TypeSourceInfo *TSI = BD->getSignatureAsWritten()) - T = TSI->getType(); - if (T.isNull()) - T = getContext().VoidTy; - if (!T->getAs()) - T = getContext().getFunctionNoProtoType(T); - T = getContext().getBlockPointerType(T); + if (D->hasLocalStorage()) { + return (isa(D) || isa(D) + ? static_cast(getStackArgumentsRegion(STC)) + : static_cast(getStackLocalsRegion(STC))); + } + assert(D->isStaticLocal()); + const Decl *STCD = STC->getDecl(); + if (isa(STCD) || isa(STCD)) + return getGlobalsRegion(MemRegion::StaticGlobalSpaceRegionKind, + getFunctionCodeRegion(cast(STCD))); - const BlockCodeRegion *BTR = - getBlockCodeRegion(BD, C.getCanonicalType(T), - STC->getAnalysisDeclContext()); - sReg = getGlobalsRegion(MemRegion::StaticGlobalSpaceRegionKind, - BTR); - } - else { - sReg = getGlobalsRegion(); - } - } - } + else if (const BlockDecl *BD = dyn_cast(STCD)) { + // FIXME: The fallback type here is totally bogus -- though it should + // never be queried, it will prevent uniquing with the real + // BlockCodeRegion. Ideally we'd fix the AST so that we always had a + // signature. + QualType T; + if (const TypeSourceInfo *TSI = BD->getSignatureAsWritten()) + T = TSI->getType(); + if (T.isNull()) + T = getContext().VoidTy; + if (!T->getAs()) + T = getContext().getFunctionNoProtoType(T); + T = getContext().getBlockPointerType(T); + + const BlockCodeRegion *BTR = + getBlockCodeRegion(BD, C.getCanonicalType(T), + STC->getAnalysisDeclContext()); + return getGlobalsRegion(MemRegion::StaticGlobalSpaceRegionKind, + BTR); } + return getGlobalsRegion(); +} +const VarRegion* MemRegionManager::getVarRegion(const VarDecl *D, + const LocationContext *LC) { + const MemRegion *sReg = nullptr; + + if (D->hasGlobalStorage() && !D->isStaticLocal()) { + sReg = getMemRegionGloballyStored(D); + + // Finally handle static locals. + } else { + sReg = getMemRegionStaticLocal(D, LC); + } return getSubRegion(D, sReg); }