From: David Majnemer Date: Tue, 14 Jun 2011 05:17:32 +0000 (+0000) Subject: Properly diagnose using abstract and incomplete types in va_arg X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0adde128d96a73864569516e684faa570e3c0333;p=clang Properly diagnose using abstract and incomplete types in va_arg - 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 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 922b0197f1..d64817b4ee 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -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; + 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>, DefaultError; diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index a44b4475ce..91821fb4d8 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -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)); diff --git a/test/Sema/varargs.c b/test/Sema/varargs.c index e399f89ae0..820567777c 100644 --- a/test/Sema/varargs.c +++ b/test/Sema/varargs.c @@ -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); +} diff --git a/test/SemaCXX/vararg-non-pod.cpp b/test/SemaCXX/vararg-non-pod.cpp index df0080fac9..3ca07b0215 100644 --- a/test/SemaCXX/vararg-non-pod.cpp +++ b/test/SemaCXX/vararg-non-pod.cpp @@ -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); +} + diff --git a/test/SemaTemplate/instantiate-expr-3.cpp b/test/SemaTemplate/instantiate-expr-3.cpp index 1febd282cc..ca88b00300 100644 --- a/test/SemaTemplate/instantiate-expr-3.cpp +++ b/test/SemaTemplate/instantiate-expr-3.cpp @@ -117,12 +117,3 @@ struct VaArg1 { template struct VaArg1<__builtin_va_list, int>; template struct VaArg1; // 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); - } -};