mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 867348 - Part 1: Add an analysis that catches calls to certain functions involving arithmetic expressions; r=jrmuizel
--HG-- extra : rebase_source : d89b16b9ab591479400a3e5e89b217a67319669d
This commit is contained in:
parent
422e060b44
commit
545e0b3667
@ -329,6 +329,49 @@ AST_MATCHER(QualType, nonheapClassAggregate) {
|
||||
AST_MATCHER(FunctionDecl, heapAllocator) {
|
||||
return MozChecker::hasCustomAnnotation(&Node, "moz_heap_allocator");
|
||||
}
|
||||
|
||||
/// This matcher will match any declaration that is marked as not accepting
|
||||
/// arithmetic expressions in its arguments.
|
||||
AST_MATCHER(Decl, noArithmeticExprInArgs) {
|
||||
return MozChecker::hasCustomAnnotation(&Node, "moz_no_arith_expr_in_arg");
|
||||
}
|
||||
|
||||
/// This matcher will match all arithmetic binary operators.
|
||||
AST_MATCHER(BinaryOperator, binaryArithmeticOperator) {
|
||||
BinaryOperatorKind opcode = Node.getOpcode();
|
||||
return opcode == BO_Mul ||
|
||||
opcode == BO_Div ||
|
||||
opcode == BO_Rem ||
|
||||
opcode == BO_Add ||
|
||||
opcode == BO_Sub ||
|
||||
opcode == BO_Shl ||
|
||||
opcode == BO_Shr ||
|
||||
opcode == BO_And ||
|
||||
opcode == BO_Xor ||
|
||||
opcode == BO_Or ||
|
||||
opcode == BO_MulAssign ||
|
||||
opcode == BO_DivAssign ||
|
||||
opcode == BO_RemAssign ||
|
||||
opcode == BO_AddAssign ||
|
||||
opcode == BO_SubAssign ||
|
||||
opcode == BO_ShlAssign ||
|
||||
opcode == BO_ShrAssign ||
|
||||
opcode == BO_AndAssign ||
|
||||
opcode == BO_XorAssign ||
|
||||
opcode == BO_OrAssign;
|
||||
}
|
||||
|
||||
/// This matcher will match all arithmetic unary operators.
|
||||
AST_MATCHER(UnaryOperator, unaryArithmeticOperator) {
|
||||
UnaryOperatorKind opcode = Node.getOpcode();
|
||||
return opcode == UO_PostInc ||
|
||||
opcode == UO_PostDec ||
|
||||
opcode == UO_PreInc ||
|
||||
opcode == UO_PreDec ||
|
||||
opcode == UO_Plus ||
|
||||
opcode == UO_Minus ||
|
||||
opcode == UO_Not;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -367,6 +410,33 @@ DiagnosticsMatcher::DiagnosticsMatcher() {
|
||||
astMatcher.addMatcher(callExpr(callee(functionDecl(allOf(heapAllocator(),
|
||||
returns(pointerType(pointee(stackClassAggregate()))))))).bind("node"),
|
||||
&stackClassChecker);
|
||||
|
||||
astMatcher.addMatcher(callExpr(allOf(hasDeclaration(noArithmeticExprInArgs()),
|
||||
anyOf(
|
||||
hasDescendant(binaryOperator(allOf(binaryArithmeticOperator(),
|
||||
hasLHS(hasDescendant(declRefExpr())),
|
||||
hasRHS(hasDescendant(declRefExpr()))
|
||||
)).bind("node")),
|
||||
hasDescendant(unaryOperator(allOf(unaryArithmeticOperator(),
|
||||
hasUnaryOperand(allOf(hasType(builtinType()),
|
||||
anyOf(hasDescendant(declRefExpr()), declRefExpr())))
|
||||
)).bind("node"))
|
||||
)
|
||||
)).bind("call"),
|
||||
&arithmeticArgChecker);
|
||||
astMatcher.addMatcher(constructExpr(allOf(hasDeclaration(noArithmeticExprInArgs()),
|
||||
anyOf(
|
||||
hasDescendant(binaryOperator(allOf(binaryArithmeticOperator(),
|
||||
hasLHS(hasDescendant(declRefExpr())),
|
||||
hasRHS(hasDescendant(declRefExpr()))
|
||||
)).bind("node")),
|
||||
hasDescendant(unaryOperator(allOf(unaryArithmeticOperator(),
|
||||
hasUnaryOperand(allOf(hasType(builtinType()),
|
||||
anyOf(hasDescendant(declRefExpr()), declRefExpr())))
|
||||
)).bind("node"))
|
||||
)
|
||||
)).bind("call"),
|
||||
&arithmeticArgChecker);
|
||||
}
|
||||
|
||||
void DiagnosticsMatcher::StackClassChecker::run(
|
||||
@ -472,6 +542,19 @@ void DiagnosticsMatcher::NonHeapClassChecker::noteInferred(QualType T,
|
||||
noteInferred(cast<ValueDecl>(cause)->getType(), Diag);
|
||||
}
|
||||
|
||||
void DiagnosticsMatcher::ArithmeticArgChecker::run(
|
||||
const MatchFinder::MatchResult &Result) {
|
||||
DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
|
||||
unsigned errorID = Diag.getDiagnosticIDs()->getCustomDiagID(
|
||||
DiagnosticIDs::Error, "cannot pass an arithmetic expression of built-in types to %0");
|
||||
const Expr *expr = Result.Nodes.getNodeAs<Expr>("node");
|
||||
if (const CallExpr *call = Result.Nodes.getNodeAs<CallExpr>("call")) {
|
||||
Diag.Report(expr->getLocStart(), errorID) << call->getDirectCallee();
|
||||
} else if (const CXXConstructExpr *ctr = Result.Nodes.getNodeAs<CXXConstructExpr>("call")) {
|
||||
Diag.Report(expr->getLocStart(), errorID) << ctr->getConstructor();
|
||||
}
|
||||
}
|
||||
|
||||
class MozCheckAction : public PluginASTAction {
|
||||
public:
|
||||
ASTConsumerPtr CreateASTConsumer(CompilerInstance &CI, StringRef fileName) override {
|
||||
|
32
build/clang-plugin/tests/TestNoArithmeticExprInArgument.cpp
Normal file
32
build/clang-plugin/tests/TestNoArithmeticExprInArgument.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
#define MOZ_NO_ARITHMETIC_EXPR_IN_ARGUMENT __attribute__((annotate("moz_no_arith_expr_in_arg")))
|
||||
|
||||
struct X {
|
||||
explicit X(int) MOZ_NO_ARITHMETIC_EXPR_IN_ARGUMENT;
|
||||
void baz(int) MOZ_NO_ARITHMETIC_EXPR_IN_ARGUMENT;
|
||||
};
|
||||
|
||||
int operator+(int, X);
|
||||
int operator+(X, int);
|
||||
int operator++(X);
|
||||
|
||||
void badArithmeticsInArgs() {
|
||||
int a;
|
||||
typedef int myint;
|
||||
myint b;
|
||||
X goodObj1(a);
|
||||
goodObj1.baz(b);
|
||||
X badObj1(a + b); // expected-error{{cannot pass an arithmetic expression of built-in types to 'X'}}
|
||||
X badObj2 = X(a ? 0 : ++a); // expected-error{{cannot pass an arithmetic expression of built-in types to 'X'}}
|
||||
X badObj3(~a); // expected-error{{cannot pass an arithmetic expression of built-in types to 'X'}}
|
||||
badObj1.baz(a - 1 - b); // expected-error{{cannot pass an arithmetic expression of built-in types to 'baz'}}
|
||||
badObj1.baz(++a); // expected-error{{cannot pass an arithmetic expression of built-in types to 'baz'}}
|
||||
badObj1.baz(a++); // expected-error{{cannot pass an arithmetic expression of built-in types to 'baz'}}
|
||||
badObj1.baz(a || b);
|
||||
badObj1.baz(a + goodObj1);
|
||||
badObj1.baz(goodObj1 + a);
|
||||
badObj1.baz(++goodObj1);
|
||||
badObj1.baz(-1);
|
||||
badObj1.baz(-1.0);
|
||||
badObj1.baz(1 + 2);
|
||||
badObj1.baz(1 << (sizeof(int)/2));
|
||||
}
|
@ -8,6 +8,7 @@ SOURCES += [
|
||||
'TestBadImplicitConversionCtor.cpp',
|
||||
'TestCustomHeap.cpp',
|
||||
'TestMustOverride.cpp',
|
||||
'TestNoArithmeticExprInArgument.cpp',
|
||||
'TestNonHeapClass.cpp',
|
||||
'TestStackClass.cpp',
|
||||
]
|
||||
|
Loading…
Reference in New Issue
Block a user