diff options
author | dim <dim@FreeBSD.org> | 2012-08-15 20:02:54 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2012-08-15 20:02:54 +0000 |
commit | 554bcb69c2d785a011a30e7db87a36a87fe7db10 (patch) | |
tree | 9abb1a658a297776086f4e0dfa6ca533de02104e /lib/Analysis/FormatString.cpp | |
parent | bb67ca86b31f67faee50bd10c3b036d65751745a (diff) | |
download | FreeBSD-src-554bcb69c2d785a011a30e7db87a36a87fe7db10.zip FreeBSD-src-554bcb69c2d785a011a30e7db87a36a87fe7db10.tar.gz |
Vendor import of clang trunk r161861:
http://llvm.org/svn/llvm-project/cfe/trunk@161861
Diffstat (limited to 'lib/Analysis/FormatString.cpp')
-rw-r--r-- | lib/Analysis/FormatString.cpp | 138 |
1 files changed, 107 insertions, 31 deletions
diff --git a/lib/Analysis/FormatString.cpp b/lib/Analysis/FormatString.cpp index ba45865..e7ea486 100644 --- a/lib/Analysis/FormatString.cpp +++ b/lib/Analysis/FormatString.cpp @@ -15,7 +15,7 @@ #include "FormatStringParsing.h" #include "clang/Basic/LangOptions.h" -using clang::analyze_format_string::ArgTypeResult; +using clang::analyze_format_string::ArgType; using clang::analyze_format_string::FormatStringHandler; using clang::analyze_format_string::FormatSpecifier; using clang::analyze_format_string::LengthModifier; @@ -229,18 +229,34 @@ clang::analyze_format_string::ParseLengthModifier(FormatSpecifier &FS, } //===----------------------------------------------------------------------===// -// Methods on ArgTypeResult. +// Methods on ArgType. //===----------------------------------------------------------------------===// -bool ArgTypeResult::matchesType(ASTContext &C, QualType argTy) const { +bool ArgType::matchesType(ASTContext &C, QualType argTy) const { + if (Ptr) { + // It has to be a pointer. + const PointerType *PT = argTy->getAs<PointerType>(); + if (!PT) + return false; + + // We cannot write through a const qualified pointer. + if (PT->getPointeeType().isConstQualified()) + return false; + + argTy = PT->getPointeeType(); + } + switch (K) { case InvalidTy: - llvm_unreachable("ArgTypeResult must be valid"); + llvm_unreachable("ArgType must be valid"); case UnknownTy: return true; case AnyCharTy: { + if (const EnumType *ETy = argTy->getAs<EnumType>()) + argTy = ETy->getDecl()->getIntegerType(); + if (const BuiltinType *BT = argTy->getAs<BuiltinType>()) switch (BT->getKind()) { default: @@ -255,7 +271,10 @@ bool ArgTypeResult::matchesType(ASTContext &C, QualType argTy) const { } case SpecificTy: { + if (const EnumType *ETy = argTy->getAs<EnumType>()) + argTy = ETy->getDecl()->getIntegerType(); argTy = C.getCanonicalType(argTy).getUnqualifiedType(); + if (T == argTy) return true; // Check for "compatible types". @@ -265,10 +284,9 @@ bool ArgTypeResult::matchesType(ASTContext &C, QualType argTy) const { break; case BuiltinType::Char_S: case BuiltinType::SChar: - return T == C.UnsignedCharTy; case BuiltinType::Char_U: case BuiltinType::UChar: - return T == C.SignedCharTy; + return T == C.UnsignedCharTy || T == C.SignedCharTy; case BuiltinType::Short: return T == C.UnsignedShortTy; case BuiltinType::UShort: @@ -319,20 +337,21 @@ bool ArgTypeResult::matchesType(ASTContext &C, QualType argTy) const { } case WIntTy: { - // Instead of doing a lookup for the definition of 'wint_t' (which - // is defined by the system headers) instead see if wchar_t and - // the argument type promote to the same type. - QualType PromoWChar = - C.getWCharType()->isPromotableIntegerType() - ? C.getPromotedIntegerType(C.getWCharType()) : C.getWCharType(); + QualType PromoArg = argTy->isPromotableIntegerType() ? C.getPromotedIntegerType(argTy) : argTy; - PromoWChar = C.getCanonicalType(PromoWChar).getUnqualifiedType(); + QualType WInt = C.getCanonicalType(C.getWIntType()).getUnqualifiedType(); PromoArg = C.getCanonicalType(PromoArg).getUnqualifiedType(); - return PromoWChar == PromoArg; + // If the promoted argument is the corresponding signed type of the + // wint_t type, then it should match. + if (PromoArg->hasSignedIntegerRepresentation() && + C.getCorrespondingUnsignedType(PromoArg) == WInt) + return true; + + return WInt == PromoArg; } case CPointerTy: @@ -358,40 +377,63 @@ bool ArgTypeResult::matchesType(ASTContext &C, QualType argTy) const { } } - llvm_unreachable("Invalid ArgTypeResult Kind!"); + llvm_unreachable("Invalid ArgType Kind!"); } -QualType ArgTypeResult::getRepresentativeType(ASTContext &C) const { +QualType ArgType::getRepresentativeType(ASTContext &C) const { + QualType Res; switch (K) { case InvalidTy: - llvm_unreachable("No representative type for Invalid ArgTypeResult"); + llvm_unreachable("No representative type for Invalid ArgType"); case UnknownTy: - return QualType(); + llvm_unreachable("No representative type for Unknown ArgType"); case AnyCharTy: - return C.CharTy; + Res = C.CharTy; + break; case SpecificTy: - return T; + Res = T; + break; case CStrTy: - return C.getPointerType(C.CharTy); + Res = C.getPointerType(C.CharTy); + break; case WCStrTy: - return C.getPointerType(C.getWCharType()); + Res = C.getPointerType(C.getWCharType()); + break; case ObjCPointerTy: - return C.ObjCBuiltinIdTy; + Res = C.ObjCBuiltinIdTy; + break; case CPointerTy: - return C.VoidPtrTy; + Res = C.VoidPtrTy; + break; case WIntTy: { - QualType WC = C.getWCharType(); - return WC->isPromotableIntegerType() ? C.getPromotedIntegerType(WC) : WC; + Res = C.getWIntType(); + break; } } - llvm_unreachable("Invalid ArgTypeResult Kind!"); + if (Ptr) + Res = C.getPointerType(Res); + return Res; } -std::string ArgTypeResult::getRepresentativeTypeName(ASTContext &C) const { +std::string ArgType::getRepresentativeTypeName(ASTContext &C) const { std::string S = getRepresentativeType(C).getAsString(); - if (Name && S != Name) - return std::string("'") + Name + "' (aka '" + S + "')"; + + std::string Alias; + if (Name) { + // Use a specific name for this type, e.g. "size_t". + Alias = Name; + if (Ptr) { + // If ArgType is actually a pointer to T, append an asterisk. + Alias += (Alias[Alias.size()-1] == '*') ? "*" : " *"; + } + // If Alias is the same as the underlying type, e.g. wchar_t, then drop it. + if (S == Alias) + Alias.clear(); + } + + if (!Alias.empty()) + return std::string("'") + Alias + "' (aka '" + S + "')"; return std::string("'") + S + "'"; } @@ -400,7 +442,7 @@ std::string ArgTypeResult::getRepresentativeTypeName(ASTContext &C) const { // Methods on OptionalAmount. //===----------------------------------------------------------------------===// -ArgTypeResult +ArgType analyze_format_string::OptionalAmount::getArgType(ASTContext &Ctx) const { return Ctx.IntTy; } @@ -676,3 +718,37 @@ bool FormatSpecifier::hasStandardLengthConversionCombination() const { } return true; } + +bool FormatSpecifier::namedTypeToLengthModifier(QualType QT, + LengthModifier &LM) { + assert(isa<TypedefType>(QT) && "Expected a TypedefType"); + const TypedefNameDecl *Typedef = cast<TypedefType>(QT)->getDecl(); + + for (;;) { + const IdentifierInfo *Identifier = Typedef->getIdentifier(); + if (Identifier->getName() == "size_t") { + LM.setKind(LengthModifier::AsSizeT); + return true; + } else if (Identifier->getName() == "ssize_t") { + // Not C99, but common in Unix. + LM.setKind(LengthModifier::AsSizeT); + return true; + } else if (Identifier->getName() == "intmax_t") { + LM.setKind(LengthModifier::AsIntMax); + return true; + } else if (Identifier->getName() == "uintmax_t") { + LM.setKind(LengthModifier::AsIntMax); + return true; + } else if (Identifier->getName() == "ptrdiff_t") { + LM.setKind(LengthModifier::AsPtrDiff); + return true; + } + + QualType T = Typedef->getUnderlyingType(); + if (!isa<TypedefType>(T)) + break; + + Typedef = cast<TypedefType>(T)->getDecl(); + } + return false; +} |