(no subject)

Hello,

In a checker I want to test whether an argument to a function call is a String literal, but I’m a bit stuck. Could anybody shed a bit of light on this?

  1. This way seems to not work (although no compile-time error), but I don’t understand why:

const Expr *arg = CE->getArg(0); // CE is a CallExpr
if ((arg != NULL) && (clang::isaclang::StringLiteral(arg))){

  1. The following does not compile:

const Expr *arg = CE->getArg(0); // CE is a CallExpr
if (StringLiteral *SL = dyn_cast(arg)) {

invalid conversion from ‘llvm::cast_retty<clang::StringLiteral, const clang::Expr*>::ret_type {aka const clang::StringLiteral*}’ to ‘clang::StringLiteral*’ [-fpermissive]
if (StringLiteral *SL = dyn_cast(arg)) {
^
3. The following does not compile, however there’s a non-const getArg() method:

Expr *arg = CE->getArg(0); // CE is a CallExpr
if (StringLiteral *SL = dyn_cast(arg)) {

error: invalid conversion from ‘const clang::Expr*’ to ‘clang::Expr*’ [-fpermissive]
Expr *arg = CE->getArg(0);
^

The analyzer traffics in const Stmt * and const Expr * everywhere, so your temporary variable for #2 and #3 should be "const StringLiteral *SL" (or just "auto *SL" now that we're using C++11).

The probable reason why this doesn't work is because there's probably an ImplicitCastExpr wrapping the StringLiteral, handling the decay from char[N] to char* (or const char *, or whatever). Depending on what you want to do, you may want to use Expr::IgnoreParenImpCasts to "look through" these kinds of filters.

Jordan

Thanks for the clarifications for cases #2 and #3.

For #1, you are right: there’s an ImplicitCastExpr wrapping the StringLiteral in the AST. I think this approach is cleaner than casting in #2 and #3, so using what you suggested works like a charm:

const Expr *arg = (CE->getArg(0))->IgnoreParenImpCasts();

Thanks a lot!