checkedc / checkedc-clang

This repo contains a version of clang that is being modified to support Checked C. Checked C is an extension to C that lets programmers write C code that is guaranteed by the compiler to be type-safe.
https://www.checkedc.org
496 stars 72 forks source link

Generic Structs for Checked C #637

Open abeln opened 5 years ago

abeln commented 5 years ago

This is a tracking issue for adding generic structs to Checked C.

abeln commented 5 years ago

MERGED

abeln commented 5 years ago

MERGED

Support for itypes.

abeln commented 5 years ago

After the itypes PR above is merged, there's one remaining TODO. See https://github.com/microsoft/checkedc-clang/pull/660#discussion_r317836958

"I think we can follow up on this in separate pull request. Please open an issue and leave some TODO's in the code.

Yes, type variables can appear inside casts too. The correct solution is to rewrite the bounds expression. TreeTransform can do that too. You can use TypeApplication::TransformExpr to transform an expression.

You would need to move the substitution class earlier in the file be able to invoke it. Alternatively, you could create a version of SubstituteTypeArgs that works for expressions.

By the way, I noticed that SubstituteTypeArgs is actually specialized for usage in a polymorphic function type application (it checks whether there the type is a function type). It isn't quite the right thing to use for substitution of types of members.

Another subtlety is that substitution may not result in any change to an expression. So before you take an action to create a new AST node based on a transformed expression, you should check to make sure that it has actually changed."

abeln commented 5 years ago

Here's another TODO for this one that David and I discussed:

Right now the representation of type applications is somewhat hacky. We use RecordDecls to represent both generic struct definitions and their applications.

e.g. struct Foo _For_any(T) is a RecordDecl(isGeneric = true, typeParameters = [T])

and a subsequent application struct Foo<int> is a RecordDecl(isApplication = true, typeArguments=[T])

What we really want here is a dedicated type for type applications, such that struct Foo<int> is its own type node TypeApp(pointer_to_foo_type, [list_of_type_arguments])

Related to this is the idea that we need to properly canonicalize type applications. Right now each type application is its own canonical type, which leads to problems when caching them. What we want is the type application TypeApp(Foo, [Arg]) to be canonicalized to TypeApp(canon(Foo), [canon(Arg)]). canon(Foo) will probably end up as Foo, but canon('Arg') might be != Arg: e.g. canon(TypeApp(Foo, T)) = TypeApp(Foo, int) if T has been typedef'ed to int.

abeln commented 5 years ago

Assigning back to @dtarditi for future work.