зеркало из https://github.com/microsoft/clang-1.git
Warn on va_start() when called with a reference parameter.
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1905.pdf 18.7p3 explicitly calls this (and some other things) out as undefined. Also move 2 other existing warnings behind the new -Wvarargs flag. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@182694 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
4c9f58f617
Коммит
b07d448a62
|
@ -246,6 +246,7 @@ def TautologicalCompare : DiagGroup<"tautological-compare",
|
||||||
def HeaderHygiene : DiagGroup<"header-hygiene">;
|
def HeaderHygiene : DiagGroup<"header-hygiene">;
|
||||||
def DuplicateDeclSpecifier : DiagGroup<"duplicate-decl-specifier">;
|
def DuplicateDeclSpecifier : DiagGroup<"duplicate-decl-specifier">;
|
||||||
def CompareDistinctPointerType : DiagGroup<"compare-distinct-pointer-types">;
|
def CompareDistinctPointerType : DiagGroup<"compare-distinct-pointer-types">;
|
||||||
|
def Varargs : DiagGroup<"varargs">;
|
||||||
|
|
||||||
def Unsequenced : DiagGroup<"unsequenced">;
|
def Unsequenced : DiagGroup<"unsequenced">;
|
||||||
// GCC name for -Wunsequenced
|
// GCC name for -Wunsequenced
|
||||||
|
|
|
@ -6090,7 +6090,9 @@ def note_empty_body_on_separate_line : Note<
|
||||||
def err_va_start_used_in_non_variadic_function : Error<
|
def err_va_start_used_in_non_variadic_function : Error<
|
||||||
"'va_start' used in function with fixed args">;
|
"'va_start' used in function with fixed args">;
|
||||||
def warn_second_parameter_of_va_start_not_last_named_argument : Warning<
|
def warn_second_parameter_of_va_start_not_last_named_argument : Warning<
|
||||||
"second parameter of 'va_start' not last named argument">;
|
"second parameter of 'va_start' not last named argument">, InGroup<Varargs>;
|
||||||
|
def warn_va_start_of_reference_type_is_undefined : Warning<
|
||||||
|
"'va_start' has undefined behavior with reference types">, InGroup<Varargs>;
|
||||||
def err_first_argument_to_va_arg_not_of_type_va_list : Error<
|
def err_first_argument_to_va_arg_not_of_type_va_list : Error<
|
||||||
"first argument to 'va_arg' is of type %0 and not 'va_list'">;
|
"first argument to 'va_arg' is of type %0 and not 'va_list'">;
|
||||||
def err_second_parameter_to_va_arg_incomplete: Error<
|
def err_second_parameter_to_va_arg_incomplete: Error<
|
||||||
|
@ -6105,7 +6107,7 @@ def warn_second_parameter_to_va_arg_ownership_qualified : Warning<
|
||||||
InGroup<NonPODVarargs>, DefaultError;
|
InGroup<NonPODVarargs>, DefaultError;
|
||||||
def warn_second_parameter_to_va_arg_never_compatible : Warning<
|
def warn_second_parameter_to_va_arg_never_compatible : Warning<
|
||||||
"second argument to 'va_arg' is of promotable type %0; this va_arg has "
|
"second argument to 'va_arg' is of promotable type %0; this va_arg has "
|
||||||
"undefined behavior because arguments will be promoted to %1">;
|
"undefined behavior because arguments will be promoted to %1">, InGroup<Varargs>;
|
||||||
|
|
||||||
def warn_return_missing_expr : Warning<
|
def warn_return_missing_expr : Warning<
|
||||||
"non-void %select{function|method}1 %0 should return a value">, DefaultError,
|
"non-void %select{function|method}1 %0 should return a value">, DefaultError,
|
||||||
|
|
|
@ -1355,6 +1355,11 @@ bool Sema::SemaBuiltinVAStart(CallExpr *TheCall) {
|
||||||
bool SecondArgIsLastNamedArgument = false;
|
bool SecondArgIsLastNamedArgument = false;
|
||||||
const Expr *Arg = TheCall->getArg(1)->IgnoreParenCasts();
|
const Expr *Arg = TheCall->getArg(1)->IgnoreParenCasts();
|
||||||
|
|
||||||
|
// These are valid if SecondArgIsLastNamedArgument is false after the next
|
||||||
|
// block.
|
||||||
|
QualType Type;
|
||||||
|
SourceLocation ParamLoc;
|
||||||
|
|
||||||
if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Arg)) {
|
if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Arg)) {
|
||||||
if (const ParmVarDecl *PV = dyn_cast<ParmVarDecl>(DR->getDecl())) {
|
if (const ParmVarDecl *PV = dyn_cast<ParmVarDecl>(DR->getDecl())) {
|
||||||
// FIXME: This isn't correct for methods (results in bogus warning).
|
// FIXME: This isn't correct for methods (results in bogus warning).
|
||||||
|
@ -1367,12 +1372,21 @@ bool Sema::SemaBuiltinVAStart(CallExpr *TheCall) {
|
||||||
else
|
else
|
||||||
LastArg = *(getCurMethodDecl()->param_end()-1);
|
LastArg = *(getCurMethodDecl()->param_end()-1);
|
||||||
SecondArgIsLastNamedArgument = PV == LastArg;
|
SecondArgIsLastNamedArgument = PV == LastArg;
|
||||||
|
|
||||||
|
Type = PV->getType();
|
||||||
|
ParamLoc = PV->getLocation();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SecondArgIsLastNamedArgument)
|
if (!SecondArgIsLastNamedArgument)
|
||||||
Diag(TheCall->getArg(1)->getLocStart(),
|
Diag(TheCall->getArg(1)->getLocStart(),
|
||||||
diag::warn_second_parameter_of_va_start_not_last_named_argument);
|
diag::warn_second_parameter_of_va_start_not_last_named_argument);
|
||||||
|
else if (Type->isReferenceType()) {
|
||||||
|
Diag(Arg->getLocStart(),
|
||||||
|
diag::warn_va_start_of_reference_type_is_undefined);
|
||||||
|
Diag(ParamLoc, diag::note_parameter_type) << Type;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ This test serves two purposes:
|
||||||
|
|
||||||
The list of warnings below should NEVER grow. It should gradually shrink to 0.
|
The list of warnings below should NEVER grow. It should gradually shrink to 0.
|
||||||
|
|
||||||
CHECK: Warnings without flags (143):
|
CHECK: Warnings without flags (141):
|
||||||
CHECK-NEXT: ext_delete_void_ptr_operand
|
CHECK-NEXT: ext_delete_void_ptr_operand
|
||||||
CHECK-NEXT: ext_enum_friend
|
CHECK-NEXT: ext_enum_friend
|
||||||
CHECK-NEXT: ext_expected_semi_decl_list
|
CHECK-NEXT: ext_expected_semi_decl_list
|
||||||
|
@ -146,8 +146,6 @@ CHECK-NEXT: warn_redeclaration_without_attribute_prev_attribute_ignored
|
||||||
CHECK-NEXT: warn_register_objc_catch_parm
|
CHECK-NEXT: warn_register_objc_catch_parm
|
||||||
CHECK-NEXT: warn_related_result_type_compatibility_class
|
CHECK-NEXT: warn_related_result_type_compatibility_class
|
||||||
CHECK-NEXT: warn_related_result_type_compatibility_protocol
|
CHECK-NEXT: warn_related_result_type_compatibility_protocol
|
||||||
CHECK-NEXT: warn_second_parameter_of_va_start_not_last_named_argument
|
|
||||||
CHECK-NEXT: warn_second_parameter_to_va_arg_never_compatible
|
|
||||||
CHECK-NEXT: warn_static_inline_explicit_inst_ignored
|
CHECK-NEXT: warn_static_inline_explicit_inst_ignored
|
||||||
CHECK-NEXT: warn_static_non_static
|
CHECK-NEXT: warn_static_non_static
|
||||||
CHECK-NEXT: warn_template_export_unsupported
|
CHECK-NEXT: warn_template_export_unsupported
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||||
|
|
||||||
|
class string;
|
||||||
|
void f(const string& s, ...) { // expected-note {{parameter of type 'const string &' is declared here}}
|
||||||
|
__builtin_va_list ap;
|
||||||
|
__builtin_va_start(ap, s); // expected-warning {{'va_start' has undefined behavior with reference types}}
|
||||||
|
}
|
Загрузка…
Ссылка в новой задаче