Mercurial > hg > CbC > CbC_llvm
diff clang/lib/AST/FormatString.cpp @ 239:173fe712db74
merge LLVM16
author | kono |
---|---|
date | Wed, 09 Nov 2022 18:03:41 +0900 |
parents | dd44ba33042e c4bab56944e8 |
children | ca573705d418 |
line wrap: on
line diff
--- a/clang/lib/AST/FormatString.cpp Wed Nov 09 17:58:30 2022 +0900 +++ b/clang/lib/AST/FormatString.cpp Wed Nov 09 18:03:41 2022 +0900 @@ -21,7 +21,6 @@ using clang::analyze_format_string::FormatSpecifier; using clang::analyze_format_string::LengthModifier; using clang::analyze_format_string::OptionalAmount; -using clang::analyze_format_string::PositionContext; using clang::analyze_format_string::ConversionSpecifier; using namespace clang; @@ -322,6 +321,12 @@ clang::analyze_format_string::ArgType::MatchKind ArgType::matchesType(ASTContext &C, QualType argTy) const { + // When using the format attribute in C++, you can receive a function or an + // array that will necessarily decay to a pointer when passed to the final + // format consumer. Apply decay before type comparison. + if (argTy->canDecayToPointerType()) + argTy = C.getDecayedType(argTy); + if (Ptr) { // It has to be a pointer. const PointerType *PT = argTy->getAs<PointerType>(); @@ -343,7 +348,7 @@ return Match; case AnyCharTy: { - if (const EnumType *ETy = argTy->getAs<EnumType>()) { + if (const auto *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()) @@ -351,17 +356,34 @@ argTy = ETy->getDecl()->getIntegerType(); } - if (const BuiltinType *BT = argTy->getAs<BuiltinType>()) + if (const auto *BT = argTy->getAs<BuiltinType>()) { + // The types are perfectly matched? switch (BT->getKind()) { + default: + break; + case BuiltinType::Char_S: + case BuiltinType::SChar: + case BuiltinType::UChar: + case BuiltinType::Char_U: + case BuiltinType::Bool: + return Match; + } + // "Partially matched" because of promotions? + if (!Ptr) { + switch (BT->getKind()) { default: break; - case BuiltinType::Char_S: - case BuiltinType::SChar: - case BuiltinType::UChar: - case BuiltinType::Char_U: - case BuiltinType::Bool: - return Match; + case BuiltinType::Int: + case BuiltinType::UInt: + return MatchPromotion; + case BuiltinType::Short: + case BuiltinType::UShort: + case BuiltinType::WChar_S: + case BuiltinType::WChar_U: + return NoMatchPromotionTypeConfusion; + } } + } return NoMatch; } @@ -378,8 +400,9 @@ if (T == argTy) return Match; - // Check for "compatible types". - if (const BuiltinType *BT = argTy->getAs<BuiltinType>()) + if (const auto *BT = argTy->getAs<BuiltinType>()) { + // Check if the only difference between them is signed vs unsigned + // if true, we consider they are compatible. switch (BT->getKind()) { default: break; @@ -390,25 +413,66 @@ case BuiltinType::Bool: if (T == C.UnsignedShortTy || T == C.ShortTy) return NoMatchTypeConfusion; - return T == C.UnsignedCharTy || T == C.SignedCharTy ? Match - : NoMatch; + if (T == C.UnsignedCharTy || T == C.SignedCharTy) + return Match; + break; case BuiltinType::Short: - return T == C.UnsignedShortTy ? Match : NoMatch; + if (T == C.UnsignedShortTy) + return Match; + break; case BuiltinType::UShort: - return T == C.ShortTy ? Match : NoMatch; + if (T == C.ShortTy) + return Match; + break; case BuiltinType::Int: - return T == C.UnsignedIntTy ? Match : NoMatch; + if (T == C.UnsignedIntTy) + return Match; + break; case BuiltinType::UInt: - return T == C.IntTy ? Match : NoMatch; + if (T == C.IntTy) + return Match; + break; case BuiltinType::Long: - return T == C.UnsignedLongTy ? Match : NoMatch; + if (T == C.UnsignedLongTy) + return Match; + break; case BuiltinType::ULong: - return T == C.LongTy ? Match : NoMatch; + if (T == C.LongTy) + return Match; + break; case BuiltinType::LongLong: - return T == C.UnsignedLongLongTy ? Match : NoMatch; + if (T == C.UnsignedLongLongTy) + return Match; + break; case BuiltinType::ULongLong: - return T == C.LongLongTy ? Match : NoMatch; - } + if (T == C.LongLongTy) + return Match; + break; + } + // "Partially matched" because of promotions? + if (!Ptr) { + switch (BT->getKind()) { + default: + break; + case BuiltinType::Int: + case BuiltinType::UInt: + if (T == C.SignedCharTy || T == C.UnsignedCharTy || + T == C.ShortTy || T == C.UnsignedShortTy || T == C.WCharTy || + T == C.WideCharTy) + return MatchPromotion; + break; + case BuiltinType::Short: + case BuiltinType::UShort: + if (T == C.SignedCharTy || T == C.UnsignedCharTy) + return NoMatchPromotionTypeConfusion; + break; + case BuiltinType::WChar_U: + case BuiltinType::WChar_S: + if (T != C.WCharTy && T != C.WideCharTy) + return NoMatchPromotionTypeConfusion; + } + } + } return NoMatch; } @@ -423,9 +487,6 @@ case BuiltinType::UChar: case BuiltinType::Char_S: case BuiltinType::SChar: -#ifndef noCbC - case BuiltinType::__Code: -#endif return Match; default: break; @@ -449,7 +510,7 @@ if (C.getCanonicalType(argTy).getUnqualifiedType() == WInt) return Match; - QualType PromoArg = argTy->isPromotableIntegerType() + QualType PromoArg = C.isPromotableIntegerType(argTy) ? C.getPromotedIntegerType(argTy) : argTy; PromoArg = C.getCanonicalType(PromoArg).getUnqualifiedType(); @@ -622,6 +683,8 @@ const char *ConversionSpecifier::toString() const { switch (kind) { + case bArg: return "b"; + case BArg: return "B"; case dArg: return "d"; case DArg: return "D"; case iArg: return "i"; @@ -743,7 +806,7 @@ break; } } - LLVM_FALLTHROUGH; + [[fallthrough]]; case LengthModifier::AsChar: case LengthModifier::AsLongLong: case LengthModifier::AsQuad: @@ -751,6 +814,8 @@ case LengthModifier::AsSizeT: case LengthModifier::AsPtrDiff: switch (CS.getKind()) { + case ConversionSpecifier::bArg: + case ConversionSpecifier::BArg: case ConversionSpecifier::dArg: case ConversionSpecifier::DArg: case ConversionSpecifier::iArg: @@ -764,7 +829,7 @@ return true; case ConversionSpecifier::FreeBSDrArg: case ConversionSpecifier::FreeBSDyArg: - return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS4(); + return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS(); default: return false; } @@ -799,7 +864,7 @@ return true; case ConversionSpecifier::FreeBSDrArg: case ConversionSpecifier::FreeBSDyArg: - return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS4(); + return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS(); default: return false; } @@ -906,6 +971,8 @@ bool FormatSpecifier::hasStandardConversionSpecifier( const LangOptions &LangOpt) const { switch (CS.getKind()) { + case ConversionSpecifier::bArg: + case ConversionSpecifier::BArg: case ConversionSpecifier::cArg: case ConversionSpecifier::dArg: case ConversionSpecifier::iArg: @@ -979,10 +1046,9 @@ bool FormatSpecifier::namedTypeToLengthModifier(QualType QT, LengthModifier &LM) { - assert(isa<TypedefType>(QT) && "Expected a TypedefType"); - const TypedefNameDecl *Typedef = cast<TypedefType>(QT)->getDecl(); - - for (;;) { + for (/**/; const auto *TT = QT->getAs<TypedefType>(); + QT = TT->getDecl()->getUnderlyingType()) { + const TypedefNameDecl *Typedef = TT->getDecl(); const IdentifierInfo *Identifier = Typedef->getIdentifier(); if (Identifier->getName() == "size_t") { LM.setKind(LengthModifier::AsSizeT); @@ -1001,12 +1067,6 @@ LM.setKind(LengthModifier::AsPtrDiff); return true; } - - QualType T = Typedef->getUnderlyingType(); - if (!isa<TypedefType>(T)) - break; - - Typedef = cast<TypedefType>(T)->getDecl(); } return false; }