Index: testsuite/g++.dg/warn/format5.C =================================================================== --- testsuite/g++.dg/warn/format5.C (revision 0) +++ testsuite/g++.dg/warn/format5.C (revision 0) @@ -0,0 +1,12 @@ +// PR c++/38980 +// { dg-options "-Wformat" } + +extern "C" +int printf(const char *format, ...) __attribute__((format(printf, 1, 2) )); + +const char fmt1[] = "Hello, %s"; + +void f() +{ + printf(fmt1, 3); // { dg-warning "expects argument" } +} Index: cp/typeck.c =================================================================== --- cp/typeck.c (revision 179649) +++ cp/typeck.c (working copy) @@ -1827,7 +1827,7 @@ decay_conversion (tree exp) /* FIXME remove? at least need to remember that this isn't really a constant expression if EXP isn't decl_constant_var_p, like with C_MAYBE_CONST_EXPR. */ - exp = decl_constant_value (exp); + exp = decl_constant_value_safe (exp); if (error_operand_p (exp)) return error_mark_node; Index: cp/init.c =================================================================== --- cp/init.c (revision 179649) +++ cp/init.c (working copy) @@ -1794,10 +1794,11 @@ build_offset_ref (tree type, tree member, bool add constant initializer, return the initializer (or, its initializers, recursively); otherwise, return DECL. If INTEGRAL_P, the initializer is only returned if DECL is an integral - constant-expression. */ + constant-expression. If RETURN_AGGREGATE_CST_OK_P, it is ok to + return an aggregate constant. */ static tree -constant_value_1 (tree decl, bool integral_p) +constant_value_1 (tree decl, bool integral_p, bool return_aggregate_cst_ok_p) { while (TREE_CODE (decl) == CONST_DECL || (integral_p @@ -1834,12 +1835,13 @@ static tree if (!init || !TREE_TYPE (init) || !TREE_CONSTANT (init) - || (!integral_p - /* Do not return an aggregate constant (of which - string literals are a special case), as we do not - want to make inadvertent copies of such entities, - and we must be sure that their addresses are the - same everywhere. */ + || (!integral_p && !return_aggregate_cst_ok_p + /* Unless RETURN_AGGREGATE_CST_OK_P is true, do not + return an aggregate constant (of which string + literals are a special case), as we do not want + to make inadvertent copies of such entities, and + we must be sure that their addresses are the + same everywhere. */ && (TREE_CODE (init) == CONSTRUCTOR || TREE_CODE (init) == STRING_CST))) break; @@ -1856,19 +1858,29 @@ static tree tree integral_constant_value (tree decl) { - return constant_value_1 (decl, /*integral_p=*/true); + return constant_value_1 (decl, /*integral_p=*/true, + /*return_aggregate_cst_ok_p=*/false); } /* A more relaxed version of integral_constant_value, used by the - common C/C++ code and by the C++ front end for optimization - purposes. */ + common C/C++ code. */ tree decl_constant_value (tree decl) { - return constant_value_1 (decl, - /*integral_p=*/processing_template_decl); + return constant_value_1 (decl, /*integral_p=*/processing_template_decl, + /*return_aggregate_cst_ok_p=*/true); } + +/* A version of integral_constant_value used by the C++ front end for + optimization purposes. */ + +tree +decl_constant_value_safe (tree decl) +{ + return constant_value_1 (decl, /*integral_p=*/processing_template_decl, + /*return_aggregate_cst_ok_p=*/false); +} /* Common subroutines of build_new and build_vec_delete. */ Index: cp/call.c =================================================================== --- cp/call.c (revision 179649) +++ cp/call.c (working copy) @@ -5703,7 +5703,7 @@ convert_like_real (conversion *convs, tree expr, t leave it as an lvalue. */ if (inner >= 0) { - expr = decl_constant_value (expr); + expr = decl_constant_value_safe (expr); if (expr == null_node && INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (totype)) /* If __null has been converted to an integer type, we do not want to warn about uses of EXPR as an integer, rather than Index: cp/cp-tree.h =================================================================== --- cp/cp-tree.h (revision 179649) +++ cp/cp-tree.h (working copy) @@ -5097,6 +5097,7 @@ extern tree create_temporary_var (tree); extern void initialize_vtbl_ptrs (tree); extern tree build_java_class_ref (tree); extern tree integral_constant_value (tree); +extern tree decl_constant_value_safe (tree); extern int diagnose_uninitialized_cst_or_ref_member (tree, bool, bool); /* in lex.c */