diff options
author | Benjamin Kramer <benny.kra@googlemail.com> | 2016-08-20 16:51:33 +0000 |
---|---|---|
committer | Benjamin Kramer <benny.kra@googlemail.com> | 2016-08-20 16:51:33 +0000 |
commit | f3b323debc949cf67cb395337fc0d5d5b26c21b9 (patch) | |
tree | d53992293b16f139b66f2effb259cbf0a057f031 /clang/lib/Analysis/FormatString.cpp | |
parent | f9fd63ad39936968e5b81a5ad5d269ffa761604c (diff) | |
download | bcm5719-llvm-f3b323debc949cf67cb395337fc0d5d5b26c21b9.tar.gz bcm5719-llvm-f3b323debc949cf67cb395337fc0d5d5b26c21b9.zip |
[Sema] Don't crash on scanf on forward-declared enums.
This is valid in GNU C, which allows pointers to incomplete enums. GCC
just pretends that the underlying type is 'int' in those cases, follow
that behavior.
llvm-svn: 279374
Diffstat (limited to 'clang/lib/Analysis/FormatString.cpp')
-rw-r--r-- | clang/lib/Analysis/FormatString.cpp | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/clang/lib/Analysis/FormatString.cpp b/clang/lib/Analysis/FormatString.cpp index 83d08b55427..0872e788c60 100644 --- a/clang/lib/Analysis/FormatString.cpp +++ b/clang/lib/Analysis/FormatString.cpp @@ -310,8 +310,13 @@ ArgType::matchesType(ASTContext &C, QualType argTy) const { return Match; case AnyCharTy: { - if (const EnumType *ETy = argTy->getAs<EnumType>()) + if (const EnumType *ETy = argTy->getAs<EnumType>()) { + // If the enum is incomplete we know nothing about the underlying type. + // Assume that it's 'int'. + if (!ETy->getDecl()->isComplete()) + return NoMatch; argTy = ETy->getDecl()->getIntegerType(); + } if (const BuiltinType *BT = argTy->getAs<BuiltinType>()) switch (BT->getKind()) { @@ -327,8 +332,14 @@ ArgType::matchesType(ASTContext &C, QualType argTy) const { } case SpecificTy: { - if (const EnumType *ETy = argTy->getAs<EnumType>()) - argTy = ETy->getDecl()->getIntegerType(); + if (const EnumType *ETy = argTy->getAs<EnumType>()) { + // If the enum is incomplete we know nothing about the underlying type. + // Assume that it's 'int'. + if (!ETy->getDecl()->isComplete()) + argTy = C.IntTy; + else + argTy = ETy->getDecl()->getIntegerType(); + } argTy = C.getCanonicalType(argTy).getUnqualifiedType(); if (T == argTy) |