]> granicus.if.org Git - clang/commitdiff
Add diagnostic for constructs like "va_arg(l, float)" which have undefined behavior...
authorEli Friedman <eli.friedman@gmail.com>
Mon, 11 Jul 2011 21:45:59 +0000 (21:45 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Mon, 11 Jul 2011 21:45:59 +0000 (21:45 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@134926 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaExpr.cpp
test/Sema/varargs.c

index 277ffcb54d6dee1e8dac64a1de8ad0a2cf3617ff..c1b09f7d6d7bf1a09e45adc06766a2edb519a8da 100644 (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,
index 9464da84c163765aaac037692295e8a39c30d2c3..2fa7b2515ef1cb3651be25c1ce1383a1555d512c 100644 (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);
index 820567777c510885d72e3d7d7dd71b8987a0fcde..07081edd1d950ca1c02acc84d1c14eea200b4533 100644 (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'}}
+}