Skip to content

[alpha.webkit.UncountedCallArgsChecker] Detect more trivial functions #81829

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,8 @@ class TrivialFunctionAnalysisVisitor

bool VisitUnaryOperator(const UnaryOperator *UO) {
// Operator '*' and '!' are allowed as long as the operand is trivial.
if (UO->getOpcode() == UO_Deref || UO->getOpcode() == UO_LNot)
if (UO->getOpcode() == UO_Deref || UO->getOpcode() == UO_AddrOf ||
UO->getOpcode() == UO_LNot)
return Visit(UO->getSubExpr());

// Other operators are non-trivial.
Expand All @@ -306,6 +307,10 @@ class TrivialFunctionAnalysisVisitor
if (auto *decl = DRE->getDecl()) {
if (isa<ParmVarDecl>(decl))
return true;
if (isa<EnumConstantDecl>(decl))
return true;
if (auto *VD = dyn_cast<VarDecl>(decl))
return VD->hasConstantInitialization() && VD->getEvaluatedValue();
}
return false;
}
Expand Down Expand Up @@ -377,6 +382,14 @@ class TrivialFunctionAnalysisVisitor
return Visit(ECE->getSubExpr());
}

bool VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *VMT) {
return Visit(VMT->getSubExpr());
}

bool VisitExprWithCleanups(const ExprWithCleanups *EWC) {
return Visit(EWC->getSubExpr());
}

bool VisitParenExpr(const ParenExpr *PE) { return Visit(PE->getSubExpr()); }

bool VisitInitListExpr(const InitListExpr *ILE) {
Expand All @@ -397,6 +410,11 @@ class TrivialFunctionAnalysisVisitor
return true;
}

bool VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E) {
// nullptr is trivial.
return true;
}

// Constant literal expressions are always trivial
bool VisitIntegerLiteral(const IntegerLiteral *E) { return true; }
bool VisitFloatingLiteral(const FloatingLiteral *E) { return true; }
Expand Down
1 change: 1 addition & 0 deletions clang/test/Analysis/Checkers/WebKit/mock-types.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ template <typename T> struct RefPtr {
RefPtr(T *t) : t(t) {}
T *get() { return t; }
T *operator->() { return t; }
const T *operator->() const { return t; }
T &operator*() { return *t; }
RefPtr &operator=(T *) { return *this; }
operator bool() { return t; }
Expand Down
95 changes: 94 additions & 1 deletion clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UncountedCallArgsChecker -verify %s

#include "mock-types.h"
//#include <type_traits>

void WTFBreakpointTrap();
void WTFCrashWithInfo(int, const char*, const char*, int);
Expand Down Expand Up @@ -60,11 +59,86 @@ NO_RETURN_DUE_TO_CRASH ALWAYS_INLINE void WTFCrashWithInfo(int line, const char*
WTFCrashWithInfoImpl(line, file, function, counter, wtfCrashArg(reason));
}

enum class Flags : unsigned short {
Flag1 = 1 << 0,
Flag2 = 1 << 1,
Flag3 = 1 << 2,
};

template<typename E> class OptionSet {
public:
using StorageType = unsigned short;

static constexpr OptionSet fromRaw(StorageType rawValue) {
return OptionSet(static_cast<E>(rawValue), FromRawValue);
}

constexpr OptionSet() = default;

constexpr OptionSet(E e)
: m_storage(static_cast<StorageType>(e)) {
}

constexpr StorageType toRaw() const { return m_storage; }

constexpr bool isEmpty() const { return !m_storage; }

constexpr explicit operator bool() const { return !isEmpty(); }

constexpr bool contains(E option) const { return containsAny(option); }
constexpr bool containsAny(OptionSet optionSet) const {
return !!(*this & optionSet);
}

constexpr bool containsAll(OptionSet optionSet) const {
return (*this & optionSet) == optionSet;
}

constexpr void add(OptionSet optionSet) { m_storage |= optionSet.m_storage; }

constexpr void remove(OptionSet optionSet)
{
m_storage &= ~optionSet.m_storage;
}

constexpr void set(OptionSet optionSet, bool value)
{
if (value)
add(optionSet);
else
remove(optionSet);
}

constexpr friend OptionSet operator|(OptionSet lhs, OptionSet rhs) {
return fromRaw(lhs.m_storage | rhs.m_storage);
}

constexpr friend OptionSet operator&(OptionSet lhs, OptionSet rhs) {
return fromRaw(lhs.m_storage & rhs.m_storage);
}

constexpr friend OptionSet operator-(OptionSet lhs, OptionSet rhs) {
return fromRaw(lhs.m_storage & ~rhs.m_storage);
}

constexpr friend OptionSet operator^(OptionSet lhs, OptionSet rhs) {
return fromRaw(lhs.m_storage ^ rhs.m_storage);
}

private:
enum InitializationTag { FromRawValue };
constexpr OptionSet(E e, InitializationTag)
: m_storage(static_cast<StorageType>(e)) {
}
StorageType m_storage { 0 };
};

class Number {
public:
Number(int v) : v(v) { }
Number(double);
Number operator+(const Number&);
const int& value() const { return v; }
private:
int v;
};
Expand Down Expand Up @@ -112,6 +186,19 @@ class RefCounted {
RefCounted& trivial18() const { RELEASE_ASSERT(this, "this must be not null"); return const_cast<RefCounted&>(*this); }
void trivial19() const { return; }

static constexpr unsigned numBits = 4;
int trivial20() { return v >> numBits; }

const int* trivial21() { return number ? &number->value() : nullptr; }

enum class Enum : unsigned short {
Value1 = 1,
Value2 = 2,
};
bool trivial22() { return enumValue == Enum::Value1; }

bool trivial23() const { return OptionSet<Flags>::fromRaw(v).contains(Flags::Flag1); }

static RefCounted& singleton() {
static RefCounted s_RefCounted;
s_RefCounted.ref();
Expand Down Expand Up @@ -170,6 +257,8 @@ class RefCounted {
}

unsigned v { 0 };
Number* number { nullptr };
Enum enumValue { Enum::Value1 };
};

RefCounted* refCountedObj();
Expand Down Expand Up @@ -208,6 +297,10 @@ class UnrelatedClass {
getFieldTrivial().trivial17(); // no-warning
getFieldTrivial().trivial18(); // no-warning
getFieldTrivial().trivial19(); // no-warning
getFieldTrivial().trivial20(); // no-warning
getFieldTrivial().trivial21(); // no-warning
getFieldTrivial().trivial22(); // no-warning
getFieldTrivial().trivial23(); // no-warning
RefCounted::singleton().trivial18(); // no-warning
RefCounted::singleton().someFunction(); // no-warning

Expand Down