/** * Provides predicates to determine whether a type is an aggregate or POD * (Plain Old Data), as defined by C++03. */ import cpp /** * Holds if `t` is a scalar type, according to the rules specified in * C++03 3.9(10): * * Arithmetic types (3.9.1), enumeration types, pointer types, and * pointer to member types (3.9.2), and cv-qualified versions of these * types (3.9.3) are collectively called scalar types. */ predicate isScalarType03(Type t) { exists(Type ut | ut = t.getUnderlyingType() | ut instanceof ArithmeticType or ut instanceof Enum or ut instanceof FunctionPointerType or ut instanceof PointerToMemberType or ut instanceof PointerType or isScalarType03(ut.(SpecifiedType).getUnspecifiedType()) ) } /** * Holds if `c` is an aggregate class, according to the rules specified in * C++03 8.5.1(1): * * An aggregate [class] is ... a class (clause 9) with no user-declared * constructors (12.1), no private or protected non-static data members * (clause 11), no base classes (clause 10), and no virtual functions * (10.3). */ predicate isAggregateClass03(Class c) { not c instanceof TemplateClass and not exists(Constructor cons | cons.getDeclaringType() = c and not cons.isCompilerGenerated() ) and not exists(Variable v | v.getDeclaringType() = c and not v.isStatic() | v.hasSpecifier("private") or v.hasSpecifier("protected") ) and not exists(c.getABaseClass()) and not exists(VirtualFunction f | f.getDeclaringType() = c) } /** * Holds if `t` is an aggregate type, according to the rules specified in * C++03 8.5.1(1): * * An aggregate is an array or a class (clause 9) with no user-declared * constructors (12.1), no private or protected non-static data members * (clause 11), no base classes (clause 10), and no virtual functions * (10.3). */ predicate isAggregateType03(Type t) { exists(Type ut | ut = t.getUnderlyingType() | ut instanceof ArrayType or isAggregateClass03(ut) ) } /** * Holds if `c` is a POD class, according to the rules specified in * C++03 9(4): * * A POD-struct is an aggregate class that has no non-static data members * of type non-POD-struct, non-POD-union (or array of such types) or * reference, and has no user-defined copy assignment operator and no * user-defined destructor. Similarly, a POD-union is an aggregate union * that has no non-static data members of type non-POD-struct, * non-POD-union (or array of such types) or reference, and has no * user-defined copy assignment operator and no user-defined destructor. * A POD class is a class that is either a POD-struct or a POD-union. */ predicate isPodClass03(Class c) { isAggregateClass03(c) and not exists(Variable v | v.getDeclaringType() = c and not v.isStatic() | not isPodType03(v.getType()) or exists(ArrayType at | at = v.getType() and not isPodType03(at.getBaseType()) ) or v.getType() instanceof ReferenceType ) and not exists(CopyAssignmentOperator o | o.getDeclaringType() = c and not o.isCompilerGenerated() ) and not exists(Destructor dest | dest.getDeclaringType() = c and not dest.isCompilerGenerated() ) } /** * Holds if `t` is a POD type, according to the rules specified in * C++03 3.9(10): * * Scalar types, POD-struct types, POD-union types (clause 9), arrays of * such types and cv-qualified versions of these types (3.9.3) are * collectively called POD types. */ predicate isPodType03(Type t) { exists(Type ut | ut = t.getUnderlyingType() | isScalarType03(ut) or isPodClass03(ut) or exists(ArrayType at | at = ut and isPodType03(at.getBaseType())) or isPodType03(ut.(SpecifiedType).getUnspecifiedType()) ) }