aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/FormatString.cpp
diff options
context:
space:
mode:
authorHans Wennborg <hans@hanshq.net>2012-08-07 08:59:46 +0000
committerHans Wennborg <hans@hanshq.net>2012-08-07 08:59:46 +0000
commit58e1e54476d610d6c33ef483f216ed8a1282d35c (patch)
tree53ddc9b5444c8e4da14bfcf799a740466ed66a3d /lib/Analysis/FormatString.cpp
parent5d435b6001fb853747426bfa47b0e0f49a736fe4 (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.cpp66
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 + "'";
}