aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaChecking.cpp
diff options
context:
space:
mode:
authorAaron Ballman <aaron@aaronballman.com>2016-09-15 14:01:10 +0000
committerAaron Ballman <aaron@aaronballman.com>2016-09-15 14:01:10 +0000
commitfc3f8f5e8633c950a4792b6a44d9c61ceda06f73 (patch)
tree3b6df7530d3fd2ea60bae858856ebb969994c6d2 /clang/lib/Sema/SemaChecking.cpp
parent3adbbc3891bc212314bb87e1c556ce5f5585a874 (diff)
downloadllvm-fc3f8f5e8633c950a4792b6a44d9c61ceda06f73.zip
llvm-fc3f8f5e8633c950a4792b6a44d9c61ceda06f73.tar.gz
llvm-fc3f8f5e8633c950a4792b6a44d9c61ceda06f73.tar.bz2
Silence false positive diagnostics regarding passing an object of enumeration type to va_start(). The underlying type for an enumeration in C is either char, signed int, or unsigned int. In the case the underlying type is chosen to be char (such as when passing -fshort-enums or using __attribute__((packed)) on the enum declaration), the enumeration can result in undefined behavior. However, when the underlying type is signed int or unsigned int (or long long as an extension), there is no undefined behavior because the types are compatible. This patch silences diagnostics for the latter while retaining the diagnostics for the former.
This patch addresses PR29140. llvm-svn: 281609
Diffstat (limited to 'clang/lib/Sema/SemaChecking.cpp')
-rw-r--r--clang/lib/Sema/SemaChecking.cpp13
1 files changed, 11 insertions, 2 deletions
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 81dc237..f3f204f 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -3240,8 +3240,17 @@ bool Sema::SemaBuiltinVAStartImpl(CallExpr *TheCall) {
Diag(TheCall->getArg(1)->getLocStart(),
diag::warn_second_arg_of_va_start_not_last_named_param);
else if (IsCRegister || Type->isReferenceType() ||
- Type->isPromotableIntegerType() ||
- Type->isSpecificBuiltinType(BuiltinType::Float)) {
+ Type->isSpecificBuiltinType(BuiltinType::Float) || [=] {
+ // Promotable integers are UB, but enumerations need a bit of
+ // extra checking to see what their promotable type actually is.
+ if (!Type->isPromotableIntegerType())
+ return false;
+ if (!Type->isEnumeralType())
+ return true;
+ const EnumDecl *ED = Type->getAs<EnumType>()->getDecl();
+ return !(ED &&
+ Context.typesAreCompatible(ED->getPromotionType(), Type));
+ }()) {
unsigned Reason = 0;
if (Type->isReferenceType()) Reason = 1;
else if (IsCRegister) Reason = 2;