[PATCH] D139759: [analyzer] Fix assertion in getAPSIntType

Balázs Benics via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Sat Dec 10 11:18:53 PST 2022


steakhal requested changes to this revision.
steakhal added a comment.
This revision now requires changes to proceed.

Nice catch.

I had a look at https://lists.llvm.org/pipermail/llvm-dev/2021-March/149216.html, and http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1169.pdf.
Your change makes sense to me.

However, I'm a bit worried that other parts of the analyzer might suffer from the same phenomenon. When I grepped for `isIntegralOrEnumerationType()`, there were like 45 mentions.
I guess, you will worry about it more than I do, but I'd recommend you to have a look at them. You might be able to craft even more crashes.

PS: I was a bit shocked that we don't have any tests mentioning `_Accum` and `_Fract`.



================
Comment at: clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h:155-156
 
-    assert(T->isIntegralOrEnumerationType() || Loc::isLocType(T));
+    assert(T->isIntegralOrEnumerationType() || T->isFixedPointType() ||
+           Loc::isLocType(T));
     return APSIntType(Ctx.getIntWidth(T),
----------------
I was thinking of using `isFixedPointOrIntegerType()`. However, that would not accept //scoped enums//.
```lang=c++
inline bool Type::isFixedPointOrIntegerType() const {
  return isFixedPointType() || isIntegerType();
}

inline bool Type::isIntegerType() const {
  if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
    return BT->getKind() >= BuiltinType::Bool &&
           BT->getKind() <= BuiltinType::Int128;
  if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) {
    // Incomplete enum types are not treated as integer types.
    // FIXME: In C++, enum types are never integer types.
    return IsEnumDeclComplete(ET->getDecl()) &&
      !IsEnumDeclScoped(ET->getDecl());     // <------------ rejects scoped enums :(
  }
  return isBitIntType();
}

inline bool Type::isIntegralOrEnumerationType() const {
  if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
    return BT->getKind() >= BuiltinType::Bool &&
           BT->getKind() <= BuiltinType::Int128;

  // Check for a complete enum type; incomplete enum types are not properly an
  // enumeration type in the sense required here.
  if (const auto *ET = dyn_cast<EnumType>(CanonicalType))
    return IsEnumDeclComplete(ET->getDecl());     // <-------- accepts scoped enums!

  return isBitIntType();
}
```

It looked so neat at first. Ah. I just had to share this.


================
Comment at: clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h:157-158
+           Loc::isLocType(T));
     return APSIntType(Ctx.getIntWidth(T),
                       !T->isSignedIntegerOrEnumerationType());
   }
----------------
I don't think you are supposed to call `isSignedIntegerOrEnumerationType()` if you have a //fixed-point// type.
```lang=C++
inline bool Type::isSignedFixedPointType() const {
  if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) {
    return ((BT->getKind() >= BuiltinType::ShortAccum &&
             BT->getKind() <= BuiltinType::LongAccum) ||
            (BT->getKind() >= BuiltinType::ShortFract &&
             BT->getKind() <= BuiltinType::LongFract) ||
            (BT->getKind() >= BuiltinType::SatShortAccum &&
             BT->getKind() <= BuiltinType::SatLongAccum) ||
            (BT->getKind() >= BuiltinType::SatShortFract &&
             BT->getKind() <= BuiltinType::SatLongFract));
  }
  return false;
}
```
By looking at the implementation of this, I don't think you could substitute that with `isSignedIntegerOrEnumerationType()`.
Am I wrong about this?

Please demonstrate this by tests.


================
Comment at: clang/test/Analysis/fixed-point.c:6-9
+long a(int c) {                                                                       
+  (long _Accum) c >> 4;
+  return c;
+}  
----------------
It had a few extra spaces. And by casting it to void we could eliminate `-Wno-unused` as well.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D139759/new/

https://reviews.llvm.org/D139759



More information about the cfe-commits mailing list