mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-26 21:38:13 +00:00
PR44684: Look through parens and similar constructs when determining
whether a call is to a builtin. We already had a general mechanism to do this but for some reason weren't using it. In passing, check for the other unary operators that can intervene in a reasonably-direct function call (we already handled '&' but missed '*' and '+'). This reverts commit aaae6b1b617378362462c1685e754813ed82b394, reinstating af80b8ccc5772c14920d4554b7ca7e15f2fad1c4, with a fix to clang-tidy.
This commit is contained in:
parent
6f5a159eab
commit
da3dc0011e
@ -34,15 +34,18 @@ void UseUncaughtExceptionsCheck::registerMatchers(MatchFinder *Finder) {
|
||||
.bind("decl_ref_expr"),
|
||||
this);
|
||||
|
||||
auto DirectCallToUncaughtException = callee(expr(ignoringImpCasts(
|
||||
declRefExpr(hasDeclaration(functionDecl(hasName(MatchText)))))));
|
||||
|
||||
// CallExpr: warning, fix-it.
|
||||
Finder->addMatcher(callExpr(hasDeclaration(functionDecl(hasName(MatchText))),
|
||||
Finder->addMatcher(callExpr(DirectCallToUncaughtException,
|
||||
unless(hasAncestor(initListExpr())))
|
||||
.bind("call_expr"),
|
||||
this);
|
||||
// CallExpr in initialisation list: warning, fix-it with avoiding narrowing
|
||||
// conversions.
|
||||
Finder->addMatcher(callExpr(hasAncestor(initListExpr()),
|
||||
hasDeclaration(functionDecl(hasName(MatchText))))
|
||||
Finder->addMatcher(callExpr(DirectCallToUncaughtException,
|
||||
hasAncestor(initListExpr()))
|
||||
.bind("init_call_expr"),
|
||||
this);
|
||||
}
|
||||
|
@ -1446,19 +1446,28 @@ void CallExpr::updateDependenciesFromArg(Expr *Arg) {
|
||||
Decl *Expr::getReferencedDeclOfCallee() {
|
||||
Expr *CEE = IgnoreParenImpCasts();
|
||||
|
||||
while (SubstNonTypeTemplateParmExpr *NTTP
|
||||
= dyn_cast<SubstNonTypeTemplateParmExpr>(CEE)) {
|
||||
CEE = NTTP->getReplacement()->IgnoreParenCasts();
|
||||
while (SubstNonTypeTemplateParmExpr *NTTP =
|
||||
dyn_cast<SubstNonTypeTemplateParmExpr>(CEE)) {
|
||||
CEE = NTTP->getReplacement()->IgnoreParenImpCasts();
|
||||
}
|
||||
|
||||
// If we're calling a dereference, look at the pointer instead.
|
||||
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(CEE)) {
|
||||
if (BO->isPtrMemOp())
|
||||
CEE = BO->getRHS()->IgnoreParenCasts();
|
||||
} else if (UnaryOperator *UO = dyn_cast<UnaryOperator>(CEE)) {
|
||||
if (UO->getOpcode() == UO_Deref)
|
||||
CEE = UO->getSubExpr()->IgnoreParenCasts();
|
||||
while (true) {
|
||||
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(CEE)) {
|
||||
if (BO->isPtrMemOp()) {
|
||||
CEE = BO->getRHS()->IgnoreParenImpCasts();
|
||||
continue;
|
||||
}
|
||||
} else if (UnaryOperator *UO = dyn_cast<UnaryOperator>(CEE)) {
|
||||
if (UO->getOpcode() == UO_Deref || UO->getOpcode() == UO_AddrOf ||
|
||||
UO->getOpcode() == UO_Plus) {
|
||||
CEE = UO->getSubExpr()->IgnoreParenImpCasts();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE))
|
||||
return DRE->getDecl();
|
||||
if (MemberExpr *ME = dyn_cast<MemberExpr>(CEE))
|
||||
@ -1469,28 +1478,11 @@ Decl *Expr::getReferencedDeclOfCallee() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// getBuiltinCallee - If this is a call to a builtin, return the builtin ID. If
|
||||
/// not, return 0.
|
||||
/// If this is a call to a builtin, return the builtin ID. If not, return 0.
|
||||
unsigned CallExpr::getBuiltinCallee() const {
|
||||
// All simple function calls (e.g. func()) are implicitly cast to pointer to
|
||||
// function. As a result, we try and obtain the DeclRefExpr from the
|
||||
// ImplicitCastExpr.
|
||||
const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(getCallee());
|
||||
if (!ICE) // FIXME: deal with more complex calls (e.g. (func)(), (*func)()).
|
||||
return 0;
|
||||
|
||||
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ICE->getSubExpr());
|
||||
if (!DRE)
|
||||
return 0;
|
||||
|
||||
const FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl());
|
||||
if (!FDecl)
|
||||
return 0;
|
||||
|
||||
if (!FDecl->getIdentifier())
|
||||
return 0;
|
||||
|
||||
return FDecl->getBuiltinID();
|
||||
auto *FDecl =
|
||||
dyn_cast_or_null<FunctionDecl>(getCallee()->getReferencedDeclOfCallee());
|
||||
return FDecl ? FDecl->getBuiltinID() : 0;
|
||||
}
|
||||
|
||||
bool CallExpr::isUnevaluatedBuiltinCall(const ASTContext &Ctx) const {
|
||||
|
@ -10684,7 +10684,7 @@ static bool getBuiltinAlignArguments(const CallExpr *E, EvalInfo &Info,
|
||||
|
||||
bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
|
||||
unsigned BuiltinOp) {
|
||||
switch (unsigned BuiltinOp = E->getBuiltinCallee()) {
|
||||
switch (BuiltinOp) {
|
||||
default:
|
||||
return ExprEvaluatorBaseTy::VisitCallExpr(E);
|
||||
|
||||
|
@ -9,7 +9,7 @@ int main() {
|
||||
struct foo s;
|
||||
|
||||
static int ary[__builtin_classify_type(a)];
|
||||
static int ary2[(__builtin_classify_type)(a)]; // expected-error{{variable length array declaration cannot have 'static' storage duration}}
|
||||
static int ary2[(__builtin_classify_type)(a)];
|
||||
static int ary3[(*__builtin_classify_type)(a)]; // expected-error{{builtin functions must be directly called}}
|
||||
|
||||
int result;
|
||||
|
@ -25,4 +25,13 @@ short somefunc();
|
||||
|
||||
short t = __builtin_constant_p(5353) ? 42 : somefunc();
|
||||
|
||||
// PR44684
|
||||
_Static_assert((__builtin_clz)(1u) >= 15, "");
|
||||
_Static_assert((__builtin_popcount)(1u) == 1, "");
|
||||
_Static_assert((__builtin_ctz)(2u) == 1, "");
|
||||
_Static_assert(_Generic(1u,unsigned:__builtin_clz)(1u) >= 15, "");
|
||||
_Static_assert(_Generic(1u,unsigned:__builtin_popcount)(1u) == 1, "");
|
||||
_Static_assert(_Generic(1u,unsigned:__builtin_ctz)(2u) == 1, "");
|
||||
|
||||
__SIZE_TYPE__ strlen(const char*);
|
||||
_Static_assert((__builtin_constant_p(1) ? (***&strlen)("foo") : 0) == 3, "");
|
||||
|
Loading…
x
Reference in New Issue
Block a user