summaryrefslogtreecommitdiffstats
path: root/lib/Analysis/FormatString.cpp
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2012-08-15 20:02:54 +0000
committerdim <dim@FreeBSD.org>2012-08-15 20:02:54 +0000
commit554bcb69c2d785a011a30e7db87a36a87fe7db10 (patch)
tree9abb1a658a297776086f4e0dfa6ca533de02104e /lib/Analysis/FormatString.cpp
parentbb67ca86b31f67faee50bd10c3b036d65751745a (diff)
downloadFreeBSD-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.cpp138
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;
+}
OpenPOWER on IntegriCloud