This is an archive of the discontinued LLVM Phabricator instance.

Extend checking of va_start builtin
ClosedPublic

Authored by aaron.ballman on Apr 18 2016, 3:52 PM.

Details

Reviewers
dblaikie
rsmith
Summary

The va_start macro currently diagnoses passing a reference as the second argument (the one representing the parameter before the ellipsis) because this is undefined behavior in C++. This patch extends the checking to cover additional cases of undefined behavior in both C and C++. The C11 Standard, 7.16.1.4p4 states, in part:

If the parameter parmN is declared with the register storage class, with a function or array type, or with a type that is not compatible with the type that results after application of the default argument promotions, the behavior is undefined.

(This is picked up by reference in C++ under [support.runtime]p3.)

This patch adds a check for default argument promotions as well as parameters declared with the register storage class. 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).

Diff Detail

Event Timeline

aaron.ballman retitled this revision from to Extend checking of va_start builtin.
aaron.ballman updated this object.
aaron.ballman added reviewers: rsmith, dblaikie.
aaron.ballman added a subscriber: cfe-commits.
rsmith added inline comments.Apr 18 2016, 4:27 PM
include/clang/Basic/DiagnosticSemaKinds.td
7417–7421

I'm not sure that

'va_start' has undefined behavior with an object declared with the register storage class

is clear enough about what object it's talking about. Can you explicitly state that the problem is with the type of the parameter name passed to va_start here, somehow?

lib/Sema/SemaChecking.cpp
2722

Where is this restriction specified? Does this only apply to C?

aaron.ballman added inline comments.Apr 18 2016, 5:10 PM
include/clang/Basic/DiagnosticSemaKinds.td
7417–7421

How about: "'va_start' has undefined behavior with a parameter declared with the 'register' keyword"?

Then again, we could reword the entire diagnostic and I wouldn't be sad. I notice that it's using the plural "types" already instead of the singular form, for instance. How about:

"Passing %select{an object of reference type|an object that undergoes default argument promotion|a parameter declared with the 'register' keyword}0 to 'va_start' is undefined behavior"

lib/Sema/SemaChecking.cpp
2722

7.16.1.4p3:

If the parameter parmN is declared with the register storage class ... the behavior is undefined.

I think this may only apply in C, actually, because [support.runtime]p3 does not mention it in its description (even as far back as C++03). Whether that's an explicit omission (to make va_start() more powerful than in C) or an oversight is kind of moot since register was removed in C++17. Thoughts?

rsmith added inline comments.Apr 18 2016, 5:20 PM
include/clang/Basic/DiagnosticSemaKinds.td
7417–7421

I think either of these is fine. (Though in the latter one, I'd say "has undefined behavior" or "results in undefined behavior" rather than "is undefined behavior".)

lib/Sema/SemaChecking.cpp
2722

I think it's an intentional difference with C. The intent of disallowing register is to allow va_start to be implemented as a macro that takes the address of the parameter. This would be ill-formed in C for a register parameter, whereas in C++ it is (was) valid to take the address of a variable declared with the register specifier.

Addressed review comments:

  • Allow the register keyword for C++ code
  • Reword the diagnostic to be a bit more clear
  • Moved the varargs.cpp test case from Sema to SemaCXX
aaron.ballman marked 6 inline comments as done.Apr 19 2016, 8:42 AM
aaron.ballman added inline comments.
lib/Sema/SemaChecking.cpp
2722

That makes sense, thank you for the explanation.

aaron.ballman marked an inline comment as done.Apr 22 2016, 1:57 PM

Ping.

rsmith accepted this revision.Apr 22 2016, 4:56 PM
rsmith edited edge metadata.
This revision is now accepted and ready to land.Apr 22 2016, 4:56 PM
aaron.ballman closed this revision.Apr 24 2016, 6:36 AM

Thanks! I've commit in r267338.

test/Sema/varargs.c