From: Eli Friedman Date: Mon, 11 Jul 2011 21:45:59 +0000 (+0000) Subject: Add diagnostic for constructs like "va_arg(l, float)" which have undefined behavior... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=46d37c10404097eed7c173b17e52693edcb66486;p=clang Add diagnostic for constructs like "va_arg(l, float)" which have undefined behavior. PR10201. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@134926 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 277ffcb54d..c1b09f7d6d 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -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>, 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, diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 9464da84c1..2fa7b2515e 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -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); diff --git a/test/Sema/varargs.c b/test/Sema/varargs.c index 820567777c..07081edd1d 100644 --- a/test/Sema/varargs.c +++ b/test/Sema/varargs.c @@ -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'}} +}