]> granicus.if.org Git - clang/commitdiff
Properly diagnose using abstract and incomplete types in va_arg
authorDavid Majnemer <david.majnemer@gmail.com>
Tue, 14 Jun 2011 05:17:32 +0000 (05:17 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Tue, 14 Jun 2011 05:17:32 +0000 (05:17 +0000)
- Move a test from test/SemaTemplate/instantiate-expr-3.cpp, it did not belong there
- Incomplete and abstract types are considered hard errors

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@132979 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaExpr.cpp
test/Sema/varargs.c
test/SemaCXX/vararg-non-pod.cpp
test/SemaTemplate/instantiate-expr-3.cpp

index 922b0197f18e0d11574f664ecdfe4d6f038757ce..d64817b4eed2fc57644a5b84f01f66488211d412 100644 (file)
@@ -3927,12 +3927,17 @@ def err_switch_incomplete_class_type : Error<
   "switch condition has incomplete class type %0">;
 def warn_empty_if_body : Warning<
   "if statement has empty body">, InGroup<EmptyBody>;
+
 def err_va_start_used_in_non_variadic_function : Error<
   "'va_start' used in function with fixed args">;
 def warn_second_parameter_of_va_start_not_last_named_argument : Warning<
   "second parameter of 'va_start' not last named argument">;
 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'">;
+def err_second_parameter_to_va_arg_incomplete: Error<
+  "second argument to 'va_arg' is of incomplete type %0">;
+def err_second_parameter_to_va_arg_abstract: Error<
+  "second argument to 'va_arg' is of abstract type %0">;
 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;
index a44b4475ce8b74337d1adf83ef1562d79ea0ac3a..91821fb4d84553f6ae8829223b2581b261e36db7 100644 (file)
@@ -9818,12 +9818,24 @@ ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc,
       << OrigExpr->getType() << E->getSourceRange());
   }
 
-  // FIXME: Check that type is complete/non-abstract
+  if (!TInfo->getType()->isDependentType()) {
+    if (RequireCompleteType(TInfo->getTypeLoc().getBeginLoc(), TInfo->getType(),
+          PDiag(diag::err_second_parameter_to_va_arg_incomplete)
+          << TInfo->getTypeLoc().getSourceRange()))
+      return ExprError();
+
+    if (RequireNonAbstractType(TInfo->getTypeLoc().getBeginLoc(),
+          TInfo->getType(),
+          PDiag(diag::err_second_parameter_to_va_arg_abstract)
+          << TInfo->getTypeLoc().getSourceRange()))
+      return ExprError();
 
-  if (!TInfo->getType()->isDependentType() && !TInfo->getType()->isPODType())
-    return ExprError(Diag(TInfo->getTypeLoc().getBeginLoc(),
-                         diag::warn_second_parameter_to_va_arg_not_pod)
-      << TInfo->getType() << TInfo->getTypeLoc().getSourceRange());
+    if (!TInfo->getType()->isPODType())
+      Diag(TInfo->getTypeLoc().getBeginLoc(),
+          diag::warn_second_parameter_to_va_arg_not_pod)
+        << TInfo->getType()
+        << TInfo->getTypeLoc().getSourceRange();
+  }
 
   QualType T = TInfo->getType().getNonLValueExprType(Context);
   return Owned(new (Context) VAArgExpr(BuiltinLoc, E, TInfo, RPLoc, T));
index e399f89ae0aa56d1318aace1b9c7909948e23888..820567777c510885d72e3d7d7dd71b8987a0fcde 100644 (file)
@@ -61,3 +61,9 @@ void f7(int a, ...) {
   __builtin_va_end(ap);
 }
 
+void f8(int a, ...) {
+  __builtin_va_list ap;
+  __builtin_va_start(ap, a);
+  (void)__builtin_va_arg(ap, void); // expected-error {{second argument to 'va_arg' is of incomplete type 'void'}}
+  __builtin_va_end(ap);
+}
index df0080fac94a0f19b8f6f279599b0d752d58821e..3ca07b0215c39c7beabe08768c6dcba8a2e0d824 100644 (file)
@@ -101,3 +101,21 @@ void t6(Foo somearg, ... ) {
   __builtin_va_start(list, somearg);
 }
 
+void t7(int n, ...) {
+  __builtin_va_list list;
+  __builtin_va_start(list, n);
+  (void)__builtin_va_arg(list, C); // expected-warning{{second argument to 'va_arg' is of non-POD type 'C'}}
+  __builtin_va_end(list);
+}
+
+struct Abstract {
+  virtual void doit() = 0; // expected-note{{unimplemented pure virtual method}}
+};
+
+void t8(int n, ...) {
+  __builtin_va_list list;
+  __builtin_va_start(list, n);
+  (void)__builtin_va_arg(list, Abstract); // expected-error{{second argument to 'va_arg' is of abstract type 'Abstract'}}
+  __builtin_va_end(list);
+}
+
index 1febd282cce901eb29267241d412fe19bf7d76d9..ca88b00300dcfa7de409a6543a96b72b5819ebd9 100644 (file)
@@ -117,12 +117,3 @@ struct VaArg1 {
 
 template struct VaArg1<__builtin_va_list, int>;
 template struct VaArg1<int, int>; // expected-note{{instantiation}}
-
-struct VaArg2 {
-  virtual void f(int n, ...) {
-    __builtin_va_list va;
-    __builtin_va_start(va, n);
-    (void)__builtin_va_arg(va, VaArg2); // expected-error {{second argument to 'va_arg' is of non-POD type 'VaArg2'}}
-    __builtin_va_end(va);
-  }
-};