diff options
author | Hans Wennborg <hans@hanshq.net> | 2012-08-07 08:59:46 +0000 |
---|---|---|
committer | Hans Wennborg <hans@hanshq.net> | 2012-08-07 08:59:46 +0000 |
commit | 58e1e54476d610d6c33ef483f216ed8a1282d35c (patch) | |
tree | 53ddc9b5444c8e4da14bfcf799a740466ed66a3d /lib/Analysis/FormatString.cpp | |
parent | 5d435b6001fb853747426bfa47b0e0f49a736fe4 (diff) |
Remove ScanfArgType and bake that logic into ArgType.
This is useful for example for %n in printf, which expects
a pointer to int with the same logic for checking as %d
would have in scanf.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@161407 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/FormatString.cpp')
-rw-r--r-- | lib/Analysis/FormatString.cpp | 66 |
1 files changed, 48 insertions, 18 deletions
diff --git a/lib/Analysis/FormatString.cpp b/lib/Analysis/FormatString.cpp index 3532a9334f..e7ea48688d 100644 --- a/lib/Analysis/FormatString.cpp +++ b/lib/Analysis/FormatString.cpp @@ -233,6 +233,19 @@ clang::analyze_format_string::ParseLengthModifier(FormatSpecifier &FS, //===----------------------------------------------------------------------===// 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("ArgType must be valid"); @@ -262,13 +275,6 @@ bool ArgType::matchesType(ASTContext &C, QualType argTy) const { argTy = ETy->getDecl()->getIntegerType(); argTy = C.getCanonicalType(argTy).getUnqualifiedType(); - if (const PointerType *PTy = argTy->getAs<PointerType>()) { - // Strip volatile qualifier from pointee type. - QualType Pointee = PTy->getPointeeType(); - Pointee.removeLocalVolatile(); - argTy = C.getPointerType(Pointee); - } - if (T == argTy) return true; // Check for "compatible types". @@ -375,35 +381,59 @@ bool ArgType::matchesType(ASTContext &C, QualType argTy) const { } QualType ArgType::getRepresentativeType(ASTContext &C) const { + QualType Res; switch (K) { case InvalidTy: 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: { - return C.getWIntType(); + Res = C.getWIntType(); + break; } } - llvm_unreachable("Invalid ArgType Kind!"); + if (Ptr) + Res = C.getPointerType(Res); + return Res; } 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 + "'"; } |