Szelethus added a comment. Hi!
Always great to see a new checker! I've started working in this project little over half a year ago, so I don't claim to be an expert, read my remarks as such! It'll be some time before I go through the entire code, but so far here are the things that caught my eye. I think you should move the checker related files to a new folder, maybe `StackOverflow/`? ================ Comment at: include/clang/StaticAnalyzer/Checkers/Checkers.td:143-146 +def StackSizeChecker : Checker<"StackSize">, + HelpText<"Warn if estimated stack usage exceeds the StackUsageLimit parameter (measured in bytes, defaults to 100000)">, + DescFile<"StackSizeChecker.cpp">; + ---------------- Alphabetical sorting? (get it? //alpha//betical? I'm sorry.) ================ Comment at: include/clang/StaticAnalyzer/Checkers/StackUsageMeasuringVisitor.h:16 +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/DenseMap.h" ---------------- Missing header guard. ================ Comment at: include/clang/StaticAnalyzer/Checkers/StackUsageMeasuringVisitor.h:25 +#include <functional> +#include <map> + ---------------- You included `map` but I don't see `std::map` anywhere? ================ Comment at: include/clang/StaticAnalyzer/Checkers/StackUsageMeasuringVisitor.h:28 +namespace clang { +namespace stack { + ---------------- Use `ento` after `clang`. Btw, does anybody know what `ento` refers to? Never got to know it :D ``` namespace clang { namespace ento { namespace stack { ================ Comment at: include/clang/StaticAnalyzer/Checkers/StackUsageMeasuringVisitor.h:57-60 + explicit StackUsageMeasuringVisitor(ASTContext &Context) + : Context(Context), ContinueTraversing(true), ExitFlag(false), + HardExit(false), ForceTemporariesToConstant(false), + ExitPredicate(nullptr) {} ---------------- Since this is the only constructor of this visitor, I think C++11 in-class member initialization would be nicer. ================ Comment at: include/clang/StaticAnalyzer/Checkers/StackUsageMeasuringVisitor.h:62 + + Usage collected() const; + ---------------- It isn't obvious to me what this function does. ================ Comment at: include/clang/StaticAnalyzer/Checkers/StackUsageMeasuringVisitor.h:64 + + // The visitor should traver post-order, because each node needs + // precalculated information in their children. ---------------- travel ================ Comment at: include/clang/StaticAnalyzer/Checkers/StackUsageMeasuringVisitor.h:94 +private: + void clear(); + bool hasUsageStored(const Stmt *S) const { ---------------- Are you sure this function belongs in a visitor? ================ Comment at: include/clang/StaticAnalyzer/Checkers/StackUsageMeasuringVisitor.h:143-144 + +} // stack +} // clang ---------------- `// end of namespace .*` ================ Comment at: lib/StaticAnalyzer/Checkers/StackSizeChecker.cpp:19 +#include "clang/AST/StmtCXX.h" +#include "clang/StaticAnalyzer/Checkers/StackUsageMeasuringVisitor.h" +#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" ---------------- I bet you can't just `#include` this without getting some nasty buildbut errors down the line, just `#include "StackUsageMeasuringVisitor.h"`. ================ Comment at: lib/StaticAnalyzer/Checkers/StackSizeChecker.cpp:25 +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include <sstream> + ---------------- Don't include standard stream libraries: https://llvm.org/docs/CodingStandards.html#include-iostream-is-forbidden ================ Comment at: lib/StaticAnalyzer/Checkers/StackSizeChecker.cpp:34 + int Used; + bool operator==(const StackInt &Other) const { return Used == Other.Used; } + void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddInteger(Used); } ---------------- If you have a conversion operator to int, do you need `operator==`? ================ Comment at: lib/StaticAnalyzer/Checkers/StackSizeChecker.cpp:41 + : public Checker<check::PreCall, check::PostCall, check::EndFunction> { + mutable std::unique_ptr<BugType> StackOverflowBugType; + ---------------- I think you don't need to make this `mutable` anymore, you can just initialize it in the constructor. ================ Comment at: lib/StaticAnalyzer/Checkers/StackSizeChecker.cpp:68-77 +int length(const llvm::ImmutableList<StackInt>& L) { + int N = 0; + auto I = L.begin(); + auto E = L.end(); + while(I != E){ + ++N; + ++I; ---------------- ``` size_t length(const llvm::ImmutableList<StackInt> &L) { int Length = 0; for (auto It = L.begin(), E = L.end(); It != E; ++It) ++Length; return Length; } ================ Comment at: lib/StaticAnalyzer/Checkers/StackSizeChecker.cpp:78 +} +} + ---------------- `// end of anonymous namespace` ================ Comment at: lib/StaticAnalyzer/Checkers/StackSizeChecker.cpp:80 + +REGISTER_LIST_WITH_PROGRAMSTATE(StackSizeList, StackInt) + ---------------- Would look better right below the definition of `StackInt`. ================ Comment at: lib/StaticAnalyzer/Checkers/StackSizeChecker.cpp:81 +REGISTER_LIST_WITH_PROGRAMSTATE(StackSizeList, StackInt) + +void StackSizeChecker::generateError(int NumBytes, SourceRange Range, ---------------- I think some dividers would help a lot: ``` //===----------------------------------------------------------------------===// // Methods for StackSizeChecker. //===----------------------------------------------------------------------===// ================ Comment at: lib/StaticAnalyzer/Checkers/StackSizeChecker.cpp:94 + // Generate the report. + std::ostringstream ErrorMessage; + ErrorMessage << "Estimated stack usage is " << NumBytes << " bytes"; ---------------- Use LLVM streams. ``` llvm::SmallString<20> WarningBuf; llvm::raw_svector_ostream OS(WarningBuf); OS << "whatever"<< " needs" << " to" << " be" << " concatenated"; ================ Comment at: lib/StaticAnalyzer/Checkers/StackSizeChecker.cpp:104 + ProgramStateRef State = C.getState(); + auto StackLevels = State->get<StackSizeList>(); + if (length(StackLevels) != countPredecessors(C)) ---------------- It isn't obvious to me why what "StackLevels" mean. Did you mean depth? ================ Comment at: lib/StaticAnalyzer/Checkers/StackSizeChecker.cpp:107-113 + stack::StackUsageMeasuringVisitor Visitor(C.getASTContext()); + auto Declaration = + dyn_cast_or_null<FunctionDecl>(C.getLocationContext()->getDecl()); + int NumBytes = + Visitor + .sumFunctionUpUntilTemplate(const_cast<FunctionDecl *>(Declaration)) + .Maximal; ---------------- You use `dyn_cast_or_null`, which to me indicates that there's a possibility of `Declaration` being null, but you never check it. ================ Comment at: lib/StaticAnalyzer/Checkers/StackSizeChecker.cpp:110-118 + int NumBytes = + Visitor + .sumFunctionUpUntilTemplate(const_cast<FunctionDecl *>(Declaration)) + .Maximal; + if (!StackLevels.isEmpty()) + NumBytes += StackLevels.getHead(); + ---------------- In essence, this looks like ``` if (/* Calculated stack usage so far*/ > StackUsageLimit) generateError(/*...*/); ``` but to me it's very obfuscated. Can you please either add more comments or move this to a separate function? ================ Comment at: lib/StaticAnalyzer/Checkers/StackSizeChecker.cpp:132-136 + int NumBytes = + Visitor.sumFunctionUpUntil(Declaration, Call.getOriginExpr()).Constant + + Visitor.sumStmtWithTemporariesExtracted(Call.getOriginExpr()).Constant; + if (!StackLevels.isEmpty()) + NumBytes += StackLevels.getHead(); ---------------- Same issue here. It would be better just to see something like `int CurrentStackUsage = getCurrentStackUsage(C);` ================ Comment at: lib/StaticAnalyzer/Checkers/StackUsageMeasuringVisitor.cpp:17 + +#include <clang/StaticAnalyzer/Checkers/StackUsageMeasuringVisitor.h> + ---------------- #include "StackUsageMeasuringVisitor.h" ================ Comment at: lib/StaticAnalyzer/Checkers/StackUsageMeasuringVisitor.cpp:22-23 + +const Usage Usage::Empty = {0, 0, false, false}; +const Usage Usage::EmptyFlagged = {0, 0, false, true}; + ---------------- Constant static data members should be in-class initialized. https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Rc-in-class-initializer ================ Comment at: lib/StaticAnalyzer/Checkers/StackUsageMeasuringVisitor.cpp:60 +} +} + ---------------- `// end of anonymous namespace` ================ Comment at: lib/StaticAnalyzer/Checkers/StackUsageMeasuringVisitor.cpp:61 +} + +void StackUsageMeasuringVisitor::putUsage(const Stmt *S, Usage U) { ---------------- ``` //===----------------------------------------------------------------------===// // Methods for StackUsageMeasuringVisitor. //===----------------------------------------------------------------------===// ================ Comment at: lib/StaticAnalyzer/Checkers/StackUsageMeasuringVisitor.cpp:64-65 + if (U.ExitFlag) { + ExitFlag = true; + ContinueTraversing = !HardExit; + } ---------------- To me it seems like `ContinueTraversing` always equals to `!ExitFlag`. Maybe remove one of them? ================ Comment at: lib/StaticAnalyzer/Checkers/StackUsageMeasuringVisitor.cpp:77 + return U; + } else { + return Usage::Empty; ---------------- https://llvm.org/docs/CodingStandards.html#don-t-use-else-after-a-return ================ Comment at: lib/StaticAnalyzer/Checkers/StackUsageMeasuringVisitor.cpp:104 + return U; + } else { + return Usage::Empty; ---------------- https://llvm.org/docs/CodingStandards.html#don-t-use-else-after-a-return Repository: rC Clang https://reviews.llvm.org/D52390 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits