Improve diagnostic checking for va_start to also warn on other instances of undefined behavior, such as a parameter declared with the register keyword in C, or a parameter of a type that undergoes default argument promotion.
This helps cover some more of the CERT secure coding rule EXP58-CPP. Pass an object of the correct type to va_start (https://www.securecoding.cert.org/confluence/display/cplusplus/EXP58-CPP.+Pass+an+object+of+the+correct+type+to+va_start).
llvm-svn: 267338
diff --git a/clang/test/Sema/varargs-x86-64.c b/clang/test/Sema/varargs-x86-64.c
index e3ded6f..0929c0d 100644
--- a/clang/test/Sema/varargs-x86-64.c
+++ b/clang/test/Sema/varargs-x86-64.c
@@ -26,11 +26,11 @@
__builtin_ms_va_start(ap, b);
}
-void __attribute__((ms_abi)) g3(float a, ...) {
+void __attribute__((ms_abi)) g3(float a, ...) { // expected-note 2{{parameter of type 'float' is declared here}}
__builtin_ms_va_list ap;
- __builtin_ms_va_start(ap, a);
- __builtin_ms_va_start(ap, (a));
+ __builtin_ms_va_start(ap, a); // expected-warning {{passing an object that undergoes default argument promotion to 'va_start' has undefined behavior}}
+ __builtin_ms_va_start(ap, (a)); // expected-warning {{passing an object that undergoes default argument promotion to 'va_start' has undefined behavior}}
}
void __attribute__((ms_abi)) g5() {
diff --git a/clang/test/Sema/varargs.c b/clang/test/Sema/varargs.c
index 82fa42b..457d84c 100644
--- a/clang/test/Sema/varargs.c
+++ b/clang/test/Sema/varargs.c
@@ -18,12 +18,11 @@
__builtin_va_start(ap, b);
}
-void f3(float a, ...)
-{
+void f3(float a, ...) { // expected-note 2{{parameter of type 'float' is declared here}}
__builtin_va_list ap;
- __builtin_va_start(ap, a);
- __builtin_va_start(ap, (a));
+ __builtin_va_start(ap, a); // expected-warning {{passing an object that undergoes default argument promotion to 'va_start' has undefined behavior}}
+ __builtin_va_start(ap, (a)); // expected-warning {{passing an object that undergoes default argument promotion to 'va_start' has undefined behavior}}
}
@@ -83,3 +82,15 @@
i = __builtin_va_start(ap, a); // expected-error {{assigning to 'int' from incompatible type 'void'}}
__builtin_va_end(ap);
}
+
+void f11(short s, ...) { // expected-note {{parameter of type 'short' is declared here}}
+ __builtin_va_list ap;
+ __builtin_va_start(ap, s); // expected-warning {{passing an object that undergoes default argument promotion to 'va_start' has undefined behavior}}
+ __builtin_va_end(ap);
+}
+
+void f12(register int i, ...) { // expected-note {{parameter of type 'int' is declared here}}
+ __builtin_va_list ap;
+ __builtin_va_start(ap, i); // expected-warning {{passing a parameter declared with the 'register' keyword to 'va_start' has undefined behavior}}
+ __builtin_va_end(ap);
+}
diff --git a/clang/test/Sema/varargs.cpp b/clang/test/Sema/varargs.cpp
deleted file mode 100644
index 48a7b2f..0000000
--- a/clang/test/Sema/varargs.cpp
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
-
-class string;
-void f(const string& s, ...) { // expected-note {{parameter of type 'const string &' is declared here}}
- __builtin_va_list ap;
- __builtin_va_start(ap, s); // expected-warning {{'va_start' has undefined behavior with reference types}}
-}
diff --git a/clang/test/SemaCXX/varargs.cpp b/clang/test/SemaCXX/varargs.cpp
new file mode 100644
index 0000000..6a18837
--- /dev/null
+++ b/clang/test/SemaCXX/varargs.cpp
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++03 -verify %s
+
+class string;
+void f(const string& s, ...) { // expected-note {{parameter of type 'const string &' is declared here}}
+ __builtin_va_list ap;
+ __builtin_va_start(ap, s); // expected-warning {{passing an object of reference type to 'va_start' has undefined behavior}}
+}
+
+void g(register int i, ...) {
+ __builtin_va_list ap;
+ __builtin_va_start(ap, i); // okay
+}