10

I have this .h file:

namespace{

class Invariant{
public:
  Invariant(z3::expr e,Instruction *i):Expr(e),I(i){
    DenseMap<Instruction*,Invariant*> FunMap = Invariants[F];
  }

private:
  //static map
  static DenseMap<Function*, DenseMap<Instruction*,Invariant*> >Invariants;

};
}//end of anonymous namespace

When I compile clang says:

Invariant.h:46:65: warning: variable '<anonymous namespace>::Invariant::Invariants' has internal linkage but is not defined
  static DenseMap<Function*, DenseMap<Instruction*,Invariant*> >Invariants;
                                                                ^
Invariant.h:26:48: note: used here
    DenseMap<Instruction*,Invariant*> FunMap = Invariants[F];

What's the problem here?

Giacomo Tagliabue
  • 1,679
  • 2
  • 15
  • 31
  • 1
    You have a static class variable. Is it properly defined anywhere for linkage resolution (loaded question, since the message you're showing makes the answer rather obvious). Static class members need to be declared in-class, then defined out-of-class. You need a `static DenseMap > Invariant::Invariants;` in the associated .cpp file for this header. – WhozCraig Apr 08 '13 at 04:42
  • If I do that, in the linking phase appears: llvm[0]: Linking Debug+Asserts Loadable Module Acsl.so Error opening '/home/giacomo/llvmtmp/llvm-csfv/Debug+Asserts/lib/Acsl.so': /home/giacomo/llvmtmp/llvm-csfv/Debug+Asserts/lib/Acsl.so: undefined symbol: _ZN12_GLOBAL__N_19Invariant10InvariantsE -load request ignored. – Giacomo Tagliabue Apr 08 '13 at 04:46
  • I don't suppose you kept the word "static" when you copied that out of your header file, did you? It should *not* be `static` declared in the .cpp file. My bad for including it. Sorry about that. – WhozCraig Apr 08 '13 at 04:49
  • Yes, I removed the `static', but same error – Giacomo Tagliabue Apr 08 '13 at 04:50
  • 1
    The only other thing I see that could potentially make things go kerplop is the anonymous namespace. I hardly profess to know their defined behavior across transition units (of even if there is such a thing) but I'd try losing that as well. Anonymous namespaces are like Greek to me (I never use them). Is this link error coming from your .so being built that is defining this class? or a separate program trying to *use* this so? – WhozCraig Apr 08 '13 at 04:52
  • Great! That solved the issue, I would have never thought that the problem was the anonymous ns. Thank you! – Giacomo Tagliabue Apr 08 '13 at 04:55
  • Neither did I until I perused [this Q&A](http://stackoverflow.com/questions/4213282/unnamed-namespace) briefly. Like I said; I never use them. Glad it works. – WhozCraig Apr 08 '13 at 04:56
  • I use anonmymous ns because LLVM policies suggest that, and I'd like to stick to them – Giacomo Tagliabue Apr 08 '13 at 05:38

1 Answers1

8

Just define it. After the class definition but before the end of the anonymous namespace add this line:

DenseMap<Function*, DenseMap<Instruction*,Invariant*> > Invariant::Invariants;

This will create the static member in every translation unit that includes this header (that's okay because it's in the anonymous namespace, which is unique to each translation unit). That's probably not what you want, but that follows from defining Invariant in an anonymous namespace. If you use a named namespace instead, you can put the definition of Invariants into a source file and have only one object shared by all the code.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165