checkers: decoupling ValueManager from GRStateManager

Hi @clang,

I'm trying to decouple ValueManager and some other classes from the GRState machinery. The goal is to make these classes reusable in a dataflow analysis framework. I've attached a patch with the sketch of a first step (it compiles fine, but shall serve as a reference only).
The most problematic thing is the placement of SValuator. Currently ValueManager holds it but I moved it to GRStateManager. Thus ValueManager can exist independently from GRStateManage and even StoreManager. In turn the SValuator now needs a StoreManager in addition to the ValueManager for construction.
But neither SValuator nor the classes derived from StoreManager need the GRStateManager anymore. Unfortunately in this first step a lot of GRState* pointers still appear in the interfaces of StoreManager and SValuator. However apparently some comments suggest that this will be changed anyway (e.g. StoreManager::getSizeInElements, StoreManager::CastResult was unused).
I had to made one functional change tough. I moved the body of SimpleSValuator::EvalCastNL/EvalCastL to ValueManager::castNonLoc/castLoc thus making these functions not longer configureable.
The questions are:
1. Is it OK to essentially make SimpleSValuator::EvalCastNL/EvalCastLnon-virtual?
2. What is the point of the SValuator class at all? Can/should it be removed? The interface and implementation can become a part of StoreManager. 3. Is it possible to remove the GRState* from the SValuator and the StoreManager interfaces alltogether?
4. In which direction is the checkers framework currently developed?

Best regards
Olaf Krzikalla

checker_1st.patch (28.6 KB)

Hi Olaf,

The point of SValuator is to build about symbolic expression values. It is designed to have a virtual interface so that we have the flexibility to change how much symbolic reasoning we want to handle, and give us a transparent way to "upgrade" the symbolic analysis by vending a virtual interface to symbolic expression construction.

ValueManager was added as a handy class so that checkers had a uniform place to construct certain kinds of SVals, as well as have a common place where the lifetime of certain SVal objects were managed. This could be incorporated directly into SValuator (and maybe it should), but the idea was to keep ValueManager simple (and non-virtual) while keeping the virtual (extensible) parts of symbolic expression construction in SValuator.

I'm fundamentally opposed to several of the changes you are suggesting (more comments inline), but I do agree with your overall motivation. I think a good first step might be to better define the roles of ValueManager and SValuator. ValueManager should be used for basic value construction and management, and SValuator for more advanced things. In particular, methods in ValueManager that currently rely on SValuator could probably just be moved to SValuator (e.g., convertToArrayIndex()). That would resolve most of the issues that you are seeing.

For some historical context, libChecker previously was libAnalysis, but the two were split apart because libAnalysis is now used by the frontend for some compiler warnings. We didn't want the compiler itself to have to depend on including the entire static analyzer core, so libAnalysis is now intended to include the common analysis components that would be used by the frontend and the static analyzer. With this in mind, would the goal be to move ValueManager to libAnalysis? I'm curious about what pieces you'd like to reuse from ValueManager with other dataflow analyses? Currently ValueManager uses the SymbolManager as well as the MemRegion abstraction. Both of these are fairly tied to the path-sensitive engine, and likely need to stay in libChecker.

Hi @clang,

I'm trying to decouple ValueManager and some other classes from the GRState machinery. The goal is to make these classes reusable in a dataflow analysis framework. I've attached a patch with the sketch of a first step (it compiles fine, but shall serve as a reference only).
The most problematic thing is the placement of SValuator. Currently ValueManager holds it but I moved it to GRStateManager. Thus ValueManager can exist independently from GRStateManage and even StoreManager. In turn the SValuator now needs a StoreManager in addition to the ValueManager for construction.
But neither SValuator nor the classes derived from StoreManager need the GRStateManager anymore. Unfortunately in this first step a lot of GRState* pointers still appear in the interfaces of StoreManager and SValuator. However apparently some comments suggest that this will be changed anyway (e.g. StoreManager::getSizeInElements, StoreManager::CastResult was unused).
I had to made one functional change tough. I moved the body of SimpleSValuator::EvalCastNL/EvalCastL to ValueManager::castNonLoc/castLoc thus making these functions not longer configureable.
The questions are:
1. Is it OK to essentially make SimpleSValuator::EvalCastNL/EvalCastLnon-virtual?

Absolutely not. These needs to stay virtual (see my second comment).

2. What is the point of the SValuator class at all? Can/should it be removed? The interface and implementation can become a part of StoreManager.

SValuator should not be removed, and it should not become a part of StoreManager. They are orthogonal concepts.

StoreManager is used for managing bindings between locations and values. SValuator is used for building SVal expressions. These are intentionally decoupled tasks so that one can engineer a new StoreManager (or SValuator) without worrying about implementing both tasks. They have virtual interfaces so that we can incrementally (and transparently) slide in new implementations of these interfaces that provide improved analysis precision, but through well-defined and thin APIs.

3. Is it possible to remove the GRState* from the SValuator and the StoreManager interfaces alltogether?

We've been gradually moving in that direction, and it may be possible at this point. That said, I think should be treated as an orthogonal problem from decoupling ValueManager from these classes. Both StoreManager and SValuator play key roles in the path-sensitive engine. If we can simplify them to not use GRState*, that's great, but afterwards we shouldn't be prohibited from adding this back into their interfaces in the future should the need arise.

4. In which direction is the checkers framework currently developed?

I need a little more context to understand this (fairly open-ended) question. What do you mean by the "checkers framework?" Are you referring to the Checker library?

Hi Ted,

> I think a good first step might be to better define the roles of
> ValueManager and SValuator. ValueManager should be used for
> basic value construction and management, and SValuator for more
> advanced things.
OK. So SValuator relies on ValueManager, but (IMHO from here on) actually should not need StoreManager. The construction of even fancy SVals should not depend on the way they are bound to Regions.
Then the StoreManager classes can be build using an particular SValuator
for the creation of SVals. In an ideal world even SValuator and the StoreManager base class don't need to use each other (as they are orthogonal).
However, currently all three classes/concepts are somehow cross-linked.
Separating ValueManager seems to be the easiest task by moving convertToArrayIndex to SValuator. But you have to expose ArrayIndexWidth and ArrayIndexTy from ValueManager (two get-functions are enough, but I don't like growing interfaces). I'm not sure if these two values are always the same. If yes, then I could imagine to move these functions to ASTContext. These two data members seem a little bit odd in ValueManager.
Once this is done you get the problem that even the StoreManager base class needs to use the SValuator. StoreManager::CastRetrievedVal could be moved to SValuator (it creates a SVal, so it might belong to SValuator), but currently I have no idea how to deal with StoreManager::getLValueElement (which also creates an SVal, but is virtual).
On the other hand the use of StoreManager should be removed from SValuator. StoreManager::CastRegion (and in turn StoreManager::MakeElementRegion) can become part of SValuator.
However, StoreManager::ArrayToPointer looks somewhat strange. Wouldn't it be possible to just move the implementation of RegionStoreManager to SValuator, thus doing always the "right" thing (Basic- and FlatStoreManager implement this function as a no-op).
Eventually we could end that first step with a layering: ValueManager, SValuator, StoreManager.
OK, after these random thoughts some more specific comments:

The point of SValuator is to build about symbolic expression values.

In understand that but I'm not convinced that a virtual interface is necessary. For me SValuator seemed to be an class which encapsulate some TODO things. Are there two different SValuator implementations thinkable (other than a basic vs. an enhanced one)?

I'm curious about what pieces you'd like to reuse from ValueManager with other dataflow analyses?

Short answer: as much as possible. Ideally also SValuator and BasicStoreManager - thats why I want to remove/replace GRState from their interfaces. You might remember of our conversation here several month ago. Back then I ended up with a solution which was sufficient at that time. Now it is time to make things more complete. I have attached my current interface header file. As you can see, ValueFlowCollector could become simpler by just using ValueManager. And the use of SValuator and BasicStoreManager could simplify my implementation further. If I would take the code as it currently is, I would need a GRStateManager (and this would open a can of worms).

4. In which direction is the checkers framework currently developed?

I need a little more context to understand this (fairly open-ended) question. What do you mean by the "checkers framework?" Are you referring to the Checker library?

Yes, I mean the Checker library. Based on your other statements I conclude that separating things is apparently indeed one of the things currently in development. So the more concrete question is: shall I wait just another month or shall I actively work on the decoupling issue?

Best regards
Olaf Krzikalla

ValueFlowAnalysis.h (4.09 KB)

Hi Ted,

I think a good first step might be to better define the roles of
ValueManager and SValuator. ValueManager should be used for
basic value construction and management, and SValuator for more
advanced things.
OK. So SValuator relies on ValueManager, but (IMHO from here on) actually should not need StoreManager. The construction of even fancy SVals should not depend on the way they are bound to Regions.

SValuators currently rely on StoreManager because pointer arithmetic is handled by StoreManagers. Thus the dependency between SValuators and StoreManagers. I don’t see this dependency going away, because all details of the memory model need to be handled by the StoreManager.

Then the StoreManager classes can be build using an particular SValuator
for the creation of SVals. In an ideal world even SValuator and the StoreManager base class don’t need to use each other (as they are orthogonal).

StoreManagers have the flexibility to lazily construct values when queried for bindings. StoreManagers need access to SValuator to have that kind of reasoning power. Thus the reverse dependency. I don’t see this going away.

However, currently all three classes/concepts are somehow cross-linked.

While a bit messy, this is actually intended. While they implement separate concepts, they are designed to work together to implement the algorithmic components of the path-sensitive engine. It turns out to implement one that we often need access to the other. That’s just how it is. We of course should remove dependencies when they are no longer needed.

Separating ValueManager seems to be the easiest task by moving convertToArrayIndex to SValuator. But you have to expose ArrayIndexWidth and ArrayIndexTy from ValueManager (two get-functions are enough, but I don’t like growing interfaces). I’m not sure if these two values are always the same.

After thinking about this some more, I’m wondering if we should just go in the reverse direction. Instead of splitting ValueManager completing off from SValuator, just integrate all of ValueManager into SValuator. That way there is one unified place where SVals are constructed.

If yes, then I could imagine to move these functions to ASTContext.

None of this should ever go into ASTContext. ASTContext is part of libAST, which is has nothing to do with the analysis component of Clang.

These two data members seem a little bit odd in ValueManager.
Once this is done you get the problem that even the StoreManager base class needs to use the SValuator. StoreManager::CastRetrievedVal could be moved to SValuator (it creates a SVal, so it might belong to SValuator), but currently I have no idea how to deal with StoreManager::getLValueElement (which also creates an SVal, but is virtual).

Per my comment above, we inherently can’t break StoreManager’s dependency on SValuator.

On the other hand the use of StoreManager should be removed from SValuator. StoreManager::CastRegion (and in turn StoreManager::MakeElementRegion) can become part of SValuator.

I agree that CastRegion can become part of SValuator (and we should do this), but the reasoning of pointer arithmetic needs to stay in the StoreManager. With this constraint, I don’t see how we can break the dependency.

However, StoreManager::ArrayToPointer looks somewhat strange. Wouldn’t it be possible to just move the implementation of RegionStoreManager to SValuator, thus doing always the “right” thing (Basic- and FlatStoreManager implement this function as a no-op).

Perhaps, but BasicStoreManager doesn’t reason about arrays, so having it return UnknownVal is actually what we want it to do. So this is actually by design, and BasicStoreManager::ArrayToPointer() is doing the right thing as far as itself is concerned.

This is how I see the breakdown. StoreManagers should handle all the management of regions, as regions represent memory and their bindings. The array to pointer decay is inherently part of how we reason about memory, and currently makes sense to keep in the StoreManager. Different StoreManagers may wish to represent about this, well, differently, so that is why that method is virtual.

FlatStoreManager is an incomplete StoreManager that is only fractionally implemented, and is currently on hold. You should honestly ignore it for now. Where commonality between it and RegionStoreManager exists we can always address with future refactoring.

Eventually we could end that first step with a layering: ValueManager, SValuator, StoreManager.
OK, after these random thoughts some more specific comments:

The more I think about it, we should just remove ValueManager entirely.

The point of SValuator is to build about symbolic expression values.

In understand that but I’m not convinced that a virtual interface is necessary. For me SValuator seemed to be an class which encapsulate some TODO things. Are there two different SValuator implementations thinkable (other than a basic vs. an enhanced one)?

Absolutely, and having the virtual interface is extremely important for three reasons:

(1) It allows us to always have a working, stable SValuator, while bringing up another one (which we just slide in).

(2) It allows us to do an apples-to-apples comparison of SValuators in terms of how they perform, their accuracy, etc.

(3) It conceivably allows users to use SValuators that are not part of libChecker.

My goal for SimpleSValuator is to keep it simple. It has a very simplistic reasoning model that does pretty well, and is good for many analysis tasks. However, it inherently can’t reason about more complicated expressions. For example:

a = foo();
b = bar();
c = baz();
return a + b + c;

Suppose ‘a’, ‘b’, and ‘c’ are all assigned symbolic values. SimpleSValuator does not know how to construct an SVal for ‘a + b + c’; it just evaluates it to UnknownVal. While this could be a TODO for SimpleSValuator, at some point there is a limit to how much reasoning we want it to perform because we want to keep it simple. Part of the reason for this is that the current ConstraintManagers can’t reason about more complicated expressions, so there is no reason to incur more analysis work to get richer SVals for which we can’t do anything meaningful with anyway.

In comparison, suppose we created a new SValuator that was built in tandem with a new ConstraintManager that could handle arbitrary linear arithmetic. These two components (each which implement a virtual interface) could be plugged in together into GRExprEngine. GRExprEngine would then transparently start building richer SVals, and then have a matching ConstraintManager that (transparently) can reason about them. This new “analysis engine” would potentially be far slower, however, than the one based on SimpleSValuator. In the cases where SimpleSValuator does just as well, then it is the clear winner. Being able to tradeoff between different levels of analysis is the inherent strength of the virtual interface.

I’m curious about what pieces you’d like to reuse from ValueManager with other dataflow analyses?

Short answer: as much as possible. Ideally also SValuator and BasicStoreManager - thats why I want to remove/replace GRState from their interfaces. You might remember of our conversation here several month ago. Back then I ended up with a solution which was sufficient at that time. Now it is time to make things more complete. I have attached my current interface header file. As you can see, ValueFlowCollector could become simpler by just using ValueManager. And the use of SValuator and BasicStoreManager could simplify my implementation further. If I would take the code as it currently is, I would need a GRStateManager (and this would open a can of worms).

I think it might be easier for me to see where this is going if I had an idea of what you don’t want to use. The more this discussion proceeds, the more I don’t believe that these pieces can be decoupled as much as you might like without putting some serious design restrictions into the path-sensitive engine.

Here’s how I see things:

(1) ValueManager can be remove by simply integrating it into SValuator. That would clean up a bunch of places in the code.

(2) StoreManager depends on SValuator. This dependency is not going away (at least not anytime soon).

(3) SValuator depends on StoreManager. This dependency is not going away unless we want to move all reasoning of pointer arithmetic to SValuator, but that’s something I strongly don’t want to do right now.

(4) The virtual interfaces in SValuator and StoreManager are not going away.

(5) It’s not clear we can’t remove SValuator’s dependency on GRState without losing reasoning power.

I think (1-4) have been addressed earlier in this email, so I’ll comment on (5). Currently GRState* is passed to SValuator because SimpleSValuator uses methods from ConstraintManager (which it can reference via a GRState object). Most of the methods in ConstraintManager depend on GRState because the GRState object has all the constraints used by the ConstraintManager. In particular, SimpleSValuator uses ConstraintManager::getSymVal(), which is a virtual method whose result depends on the current GRState. Thus I’m not really certain this dependency can be severed unless we sever the dependency between SValuator and ConstraintManager.

  1. In which direction is the checkers framework currently developed?

I need a little more context to understand this (fairly open-ended) question. What do you mean by the “checkers framework?” Are you referring to the Checker library?

Yes, I mean the Checker library. Based on your other statements I conclude that separating things is apparently indeed one of the things currently in development. So the more concrete question is: shall I wait just another month or shall I actively work on the decoupling issue?

This kind of refactoring work is gradually done over time as people see a need or they otherwise have interest in doing the cleanup work. Most activity on libChecker is on other areas right now (e.g., bringing up C++ support), and not refactoring these other pieces. Nobody else aside from you has expressed interest in reusing these components in a different context, so you will probably need to drive this work. That said, it’s not clear to me where this is heading. While I very much want the components of the analyzer to be reusable for other purposes, I’m not willing to sacrifice key aspects (many which I have mentioned) of the modular design of the path-sensitive engine. It’s also not clear to me what is the transitive closure of components that you are happy with using, since it seems you are interested in using both SValuator and the StoreManager (which inherently rely on a bunch of other stuff).

Anyhow, let’s keep discussing this, and see what we can do.

I think it might be easier for me to see where this is going if I had an
idea of what you *don't* want to use.

Maybe that's indeed the right question. To start again: my only goal is to know if two expressions refer to the same memory location (with former assignments taken into consideration). The memory location is represented by a MemRegion and my reasoning engine is already based on SVals. However I reason over basic blocks only (only parts of a function) and I want to control which statements are analyzed.
Of course my reasoning holds an internal state too, which holds the binding of SVals to MemRegions. That said, I have no problem with GRState as it is. Indeed, this and StoreManager provides some functionality which I currently have implemented by my own (but like to get rid off).
A fundamental difference is that I actually have only one state (which changes or gets extended when a new assignment is evaluated). Thus I don't need all the ExplodedNode stuff of GRExprEngine.
Another difference is the overall purpose of my analysis: it is not for bug reporting, but for code optimization. Thus I don't need the diagnostic part of AnalysisManager.
Unfortunately it is currently not possible to use only some parts of the GR framework. If you stick on GRState, you need GRStateManager, which in turn needs GRSubEngine, which eventually needs an AnalysisManager, which I don't want to use in its current form.
In addition, I initially thought that I can control the generation of ExplodedNodes in GRExprEngine so, that there is always only one successor node representing the actual state. But that attempt failed too. Thus I have mentally abandoned the GR* framework.
However I still have hope that I can use other parts like the building of SVals from binary expressions as it is done in SValuator.
Maybe I should just left the triumvirate of ValueManager, SValuator and StoreManager to your disposal and just introduce an abstraction layer for GRState. A very quick check shows, that the only functions of GRState used by StoreManager and SValuator are getStore, getSymVal and getSVal. Introducing an ABC as base class of GRState
could decouple the three classes (and their subclasses) from the GREngine (and ConstraintManager too). Of course I could go even one step higher and try to decouple GRStateManager from GRSubEngine (or change GRSubEngine).
The bottom line is that I actually have no idea where I can or shall make the cut between the actual GR framework and the underlying helper classes. You claim that it is all tightly coupled.

> Currently GRState* is passed to SValuator because

SimpleSValuator uses methods from ConstraintManager (which it can
reference via a GRState object).

I wouldn't go so far to say that SValuator uses ConstraintManager. It just uses 'any' method to retrieve the integer value of a symbol.

In particular,
SimpleSValuator uses ConstraintManager::getSymVal(), which is a virtual
method whose result depends on the current GRState. Thus I'm not really
certain this dependency can be severed unless we sever the dependency
between SValuator and ConstraintManager.

But I don't see why it is bad to sever this dependency?

> Nobody else aside

from you has expressed interest in reusing these components in a
different context, so you will probably need to drive this work.

Several month ago someone asked about taint analysis, subject was "Help with Taint analysis".

since it seems you are interested in using both SValuator and the
StoreManager

Indeed.

> (which inherently rely on a bunch of other stuff).
And that's what I want to change.

Best regards
Olaf Krzikalla

I think it might be easier for me to see where this is going if I had an
idea of what you *don't* want to use.

Maybe that's indeed the right question. To start again: my only goal is to know if two expressions refer to the same memory location (with former assignments taken into consideration). The memory location is represented by a MemRegion and my reasoning engine is already based on SVals.

Right. So the "data" pieces you need are MemRegions, SVals, symbols (which are used by the first two). You also need all the "builder" pieces for these objects.

However I reason over basic blocks only (only parts of a function) and I want to control which statements are analyzed.

Sure. You basically want to substitute GRExprEngine with something else.

Of course my reasoning holds an internal state too, which holds the binding of SVals to MemRegions. That said, I have no problem with GRState as it is. Indeed, this and StoreManager provides some functionality which I currently have implemented by my own (but like to get rid off).

Okay. Makes sense.

A fundamental difference is that I actually have only one state (which changes or gets extended when a new assignment is evaluated). Thus I don't need all the ExplodedNode stuff of GRExprEngine.

Makes sense.

Another difference is the overall purpose of my analysis: it is not for bug reporting, but for code optimization. Thus I don't need the diagnostic part of AnalysisManager.

Okay, that's a good point. AnalysisManager can possibly be refactored into parts that care just about "analysis" and those about bug-finding.

Unfortunately it is currently not possible to use only some parts of the GR framework. If you stick on GRState, you need GRStateManager, which in turn needs GRSubEngine, which eventually needs an AnalysisManager, which I don't want to use in its current form.

Makes sense.

First, I'd like to double GRStateManager from GRSubEngine. That coupling seems wrong anyway, and I'll look into breaking that dependency.

Concerning AnalysisManager, I think it's realistic for me to look into separating that into pieces needed just for raw analysis, and those for bug finding. I need to think about this a bit more.

In addition, I initially thought that I can control the generation of ExplodedNodes in GRExprEngine so, that there is always only one successor node representing the actual state. But that attempt failed too. Thus I have mentally abandoned the GR* framework.

Makes sense. It's not the right tool for your task.

However I still have hope that I can use other parts like the building of SVals from binary expressions as it is done in SValuator.
Maybe I should just left the triumvirate of ValueManager, SValuator and StoreManager to your disposal and just introduce an abstraction layer for GRState. A very quick check shows, that the only functions of GRState used by StoreManager and SValuator are getStore, getSymVal and getSVal. Introducing an ABC as base class of GRState
could decouple the three classes (and their subclasses) from the GREngine (and ConstraintManager too). Of course I could go even one step higher and try to decouple GRStateManager from GRSubEngine (or change GRSubEngine).
The bottom line is that I actually have no idea where I can or shall make the cut between the actual GR framework and the underlying helper classes. You claim that it is all tightly coupled.

I think a reasonable starting point is to try and sever GRStateManager from GRSubEngine.

A follow-on simplification may be to eliminate ValueManager entirely, since that functionality probably just belongs in SValuator (and you voiced interest in re-using SValuator yourself).

> Currently GRState* is passed to SValuator because

SimpleSValuator uses methods from ConstraintManager (which it can
reference via a GRState object).

I wouldn't go so far to say that SValuator uses ConstraintManager. It just uses 'any' method to retrieve the integer value of a symbol.

The integer value of a symbol is defined by the constraints on that value. That's why ConstraintManager is involved.

That said, we can possibly factor this better, lifting the assumption out of SValuator that it is talking to ConstraintManager.

In particular,
SimpleSValuator uses ConstraintManager::getSymVal(), which is a virtual
method whose result depends on the current GRState. Thus I'm not really
certain this dependency can be severed unless we sever the dependency
between SValuator and ConstraintManager.

But I don't see why it is bad to sever this dependency?

I think the dependency can be severed only if we replace it with something more generic. For example, GRExprEngine passes an object to SValuator (or provides one when SValuator is created) that gives the SValuator a little more context on how to perform these queries. This would be a layer of indirection, allowing the SValuator to talk to the ConstraintManager, but not assume that is what it is doing. In this way, GRExprEngine can continue to use SValuator in a way more optimal for it and other clients (such as your code) can use SValuator without it depending on ConstraintManager.

I'll need to think about the right APIs and abstraction here, as it is an important refactoring.

> Nobody else aside

from you has expressed interest in reusing these components in a
different context, so you will probably need to drive this work.

Several month ago someone asked about taint analysis, subject was "Help with Taint analysis".

That's a fair point, but that conversation never when to this level of detail about the use of specific pieces of the libChecker library.

since it seems you are interested in using both SValuator and the
StoreManager

Indeed.

> (which inherently rely on a bunch of other stuff).
And that's what I want to change.

Makes sense.

I can't promise you an immediate turnaround here. What I'd like to do is to stage this refactoring, so I can see what makes sense. There's a bunch of cleanups I want to do the analyzer core anyway, especially since implementing C++ support appears to be getting some critical momentum.

Hi Ted,

I think a reasonable starting point is to try and sever GRStateManager from GRSubEngine.

I've attached the probably most pragmatic approach to this mail. Making the GREngine in GRStateManager a pointer that can be 0 and adding another c'tor which doesn't rely on the manager creator functions (in order to enable manager c'tors with heterogenous argument lists) just made the trick.
The question is whether you can live with this hack or how the ProcessRegionChange/WantsRegionChangeUpdate functions can be refactored out of GRSubEngine otherwise. Another c'tor in GRStateManager is surely unavoidable due to the manager creator functions.
While you are going to think about this I'll try to answer the question whether I can use that GRStateManager for my problem. I'll let you know later this week.

Best Olaf

checker_2nd.patch (3.89 KB)

I think this is a reasonable tradeoff. I still like to decouple GRExprEngine from GRStateManager, but this is definitely a step in the right direction. We should probably add a comment above the new constructor indicating that it is for clients that don't want to use GRExprEngine with GRStateManager, since it will be unused elsewhere in libChecker. That way when the refactoring eventually happens we will know if that constructor can safely be removed.