@@ -781,9 +781,25 @@ struct LibcFunNamePrefixSuffixParser {
781781 }
782782};
783783
784+ // Constant fold a conditional expression 'cond ? A : B' to
785+ // - 'A', if 'cond' has constant true value;
786+ // - 'B', if 'cond' has constant false value.
787+ static const Expr *tryConstantFoldConditionalExpr (const Expr *E,
788+ const ASTContext &Ctx) {
789+ // FIXME: more places can use this function
790+ if (const auto *CE = dyn_cast<ConditionalOperator>(E)) {
791+ bool CondEval;
792+
793+ if (CE->getCond ()->EvaluateAsBooleanCondition (CondEval, Ctx))
794+ return CondEval ? CE->getLHS () : CE->getRHS ();
795+ }
796+ return E;
797+ }
798+
784799// A pointer type expression is known to be null-terminated, if it has the
785800// form: E.c_str(), for any expression E of `std::string` type.
786- static bool isNullTermPointer (const Expr *Ptr) {
801+ static bool isNullTermPointer (const Expr *Ptr, ASTContext &Ctx) {
802+ Ptr = tryConstantFoldConditionalExpr (Ptr, Ctx);
787803 if (isa<clang::StringLiteral>(Ptr->IgnoreParenImpCasts ()))
788804 return true ;
789805 if (isa<PredefinedExpr>(Ptr->IgnoreParenImpCasts ()))
@@ -874,7 +890,7 @@ static bool hasUnsafeFormatOrSArg(const CallExpr *Call, const Expr *&UnsafeArg,
874890
875891 const Expr *Arg = Call->getArg (ArgIdx);
876892
877- if (isNullTermPointer (Arg))
893+ if (isNullTermPointer (Arg, Ctx ))
878894 // If Arg is a null-terminated pointer, it is safe anyway.
879895 return true ; // continue parsing
880896
@@ -922,8 +938,8 @@ static bool hasUnsafeFormatOrSArg(const CallExpr *Call, const Expr *&UnsafeArg,
922938 // (including the format argument) is unsafe pointer.
923939 return llvm::any_of (
924940 llvm::make_range (Call->arg_begin () + FmtArgIdx, Call->arg_end ()),
925- [&UnsafeArg](const Expr *Arg) -> bool {
926- if (Arg->getType ()->isPointerType () && !isNullTermPointer (Arg)) {
941+ [&UnsafeArg, &Ctx ](const Expr *Arg) -> bool {
942+ if (Arg->getType ()->isPointerType () && !isNullTermPointer (Arg, Ctx )) {
927943 UnsafeArg = Arg;
928944 return true ;
929945 }
@@ -1175,7 +1191,7 @@ static bool hasUnsafePrintfStringArg(const CallExpr &Node, ASTContext &Ctx,
11751191 // We don't really recognize this "normal" printf, the only thing we
11761192 // can do is to require all pointers to be null-terminated:
11771193 for (const auto *Arg : Node.arguments ())
1178- if (Arg->getType ()->isPointerType () && !isNullTermPointer (Arg)) {
1194+ if (Arg->getType ()->isPointerType () && !isNullTermPointer (Arg, Ctx )) {
11791195 Result.addNode (Tag, DynTypedNode::create (*Arg));
11801196 return true ;
11811197 }
0 commit comments