Add diagnostic for constructs like "va_arg(l, float)" which have undefined behavior. PR10201.

llvm-svn: 134926
This commit is contained in:
Eli Friedman 2011-07-11 21:45:59 +00:00
parent 8532db2ec4
commit 6290ae476e
3 changed files with 29 additions and 0 deletions

View File

@ -4208,6 +4208,9 @@ def err_second_parameter_to_va_arg_abstract: Error<
def warn_second_parameter_to_va_arg_not_pod : Warning<
"second argument to 'va_arg' is of non-POD type %0">,
InGroup<DiagGroup<"non-pod-varargs">>, DefaultError;
def warn_second_parameter_to_va_arg_never_compatible : Warning<
"second argument to 'va_arg' is of promotable type %0; this va_arg has "
"undefined behavior because arguments will be promoted to %1">;
def warn_return_missing_expr : Warning<
"non-void %select{function|method}1 %0 should return a value">, DefaultError,

View File

@ -8570,6 +8570,23 @@ ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc,
diag::warn_second_parameter_to_va_arg_not_pod)
<< TInfo->getType()
<< TInfo->getTypeLoc().getSourceRange();
// Check for va_arg where arguments of the given type will be promoted
// (i.e. this va_arg is guaranteed to have undefined behavior).
QualType PromoteType;
if (TInfo->getType()->isPromotableIntegerType()) {
PromoteType = Context.getPromotedIntegerType(TInfo->getType());
if (Context.typesAreCompatible(PromoteType, TInfo->getType()))
PromoteType = QualType();
}
if (TInfo->getType()->isSpecificBuiltinType(BuiltinType::Float))
PromoteType = Context.DoubleTy;
if (!PromoteType.isNull())
Diag(TInfo->getTypeLoc().getBeginLoc(),
diag::warn_second_parameter_to_va_arg_never_compatible)
<< TInfo->getType()
<< PromoteType
<< TInfo->getTypeLoc().getSourceRange();
}
QualType T = TInfo->getType().getNonLValueExprType(Context);

View File

@ -67,3 +67,12 @@ void f8(int a, ...) {
(void)__builtin_va_arg(ap, void); // expected-error {{second argument to 'va_arg' is of incomplete type 'void'}}
__builtin_va_end(ap);
}
enum E { x = -1, y = 2, z = 10000 };
void f9(__builtin_va_list args)
{
(void)__builtin_va_arg(args, float); // expected-warning {{second argument to 'va_arg' is of promotable type 'float'}}
(void)__builtin_va_arg(args, enum E); // Don't warn here in C
(void)__builtin_va_arg(args, short); // expected-warning {{second argument to 'va_arg' is of promotable type 'short'}}
(void)__builtin_va_arg(args, char); // expected-warning {{second argument to 'va_arg' is of promotable type 'char'}}
}