6

I am using Clang as a syntax checker in my C++ project. It's called through Flycheck in Emacs, and I am getting an annoying use of undeclared identifier error, the following Minimal Working Example to illustrates the problem:

In file testnamepace.cpp:

#include "testnamespace.hpp"

int main() {
    const unsigned DIM = 3;
    testnamespace::A<DIM> a;
    a.f();
    a.g();
    return 0;
}

In file testnamespace.hpp:

#ifndef testnamespace_h
#define testnamespace_h

#include <iostream>

namespace testnamespace {
    // My code uses lots of templates so this MWE uses a class template
    template <unsigned DIM> class A;
}

template <unsigned DIM>
class testnamespace::A{
public:
    static const unsigned dim = DIM;

    A() {std::cout << "A(): dim = " << dim << std::endl;}

    // in my case some functions are defined in a .hpp file...
    void f() {
        std::cout << "call f()" << std::endl;
    }

    // ...and others are defined in a .ipp file
    void g();
};

#include "testnamespace.ipp"
#endif

In file testnamespace.ipp:

template <unsigned DIM>
void testnamespace::A<DIM>::g() {
//   ^^^^^^^^^^^^^ this results in the following error:
//   testnamespace.ipp:2:6:error: use of undeclared identifier 'testnamespace' (c/c++-clang)
    std::cout << "g()" << std::endl;
}

Since the code compiles with no warning using g++ -Wall testnamespace.cpp -o testnamespace (gcc version 4.7.2) I am wondering if this is an error in my coding or if it's just a 'feature' of using Clang.

mkm
  • 673
  • 5
  • 21
  • Try putting the definition in "namespace testnamespace {" ... "}", instead of adding "testnamespace::" on the name. – Michael Aaron Safyan Jan 21 '14 at 11:56
  • Can't reproduce. You'd get that error if you accidentally included the `ipp` header instead of the `hpp` header; but your test case compiles with no error. – Mike Seymour Jan 21 '14 at 11:57
  • @MichaelAaronSafyan ok, I tried that in the .ipp file is that where you mean? I tried that and instead I get this error: `testnamespace.ipp:3:11:error: expected ';' after top level declarator (c/c++-clang)` – mkm Jan 21 '14 at 12:01
  • @MichaelAaronSafyan: That shouldn't be necessary. This form is better, since it prevents you from accidentally declaring a new function when you intend to definw the already-declared function. – Mike Seymour Jan 21 '14 at 12:02
  • @MikeSeymour Thanks for the comment, I have double checked that my code is exactly as I wrote it here. Could it be to do with my version of Clang? – mkm Jan 21 '14 at 12:02
  • @mkm: That seems unlikely; the compiler would need to be badly broken to fail to compile this. What version is it? How exactly are you compiling it? Could there be another header on the search path with the same name? Try the `-E` (preprocess only) option, to see exactly which headers it's including and what declarations it's finding in them. – Mike Seymour Jan 21 '14 at 12:08
  • `$ clang --version` gives: `Ubuntu clang version 3.0-6ubuntu3 (tags/RELEASE_30/final) (based on LLVM 3.0)` – mkm Jan 21 '14 at 12:08
  • @MikeSeymour The code does compile and returns no warnings, I'm just wondering about the Clang error. `$ gcc --version` returns: `gcc (Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2`. I tried your suggestion `$ gcc -E testnamespace.cpp > out`, at the bottom of `out` I see all my code minus the comments, searching for *pp doesn't see to result in anything suspicious. – mkm Jan 21 '14 at 12:18
  • @mkm: Try `clang -E`, since you say it's Clang that fails. If GCC works, then it won't tell you anything useful about why a different compiler fails. (For what it's worth, your code works for me with exactly that version of Clang). – Mike Seymour Jan 21 '14 at 12:23
  • @MikeSeymour Oh opps :) I tried with `$ clang++ -Wall -Wextra testnamespace.cpp -o testnamespace` and everything works, I also tried `clang++ -fsyntax_only testnamespace.cpp` and that works. I am using Emacs flycheck to drive clang I guess this could mean the problem is there, since when calling clang manually everything is fine? I should have mentioned that sorry... – mkm Jan 21 '14 at 12:35
  • Perhaps flycheck is checking "testnamespace.ipp" as C instead of C++? I have zero familiarity with the tool. If it's doing something "smart" with filenames to determine what is C and what is C++ - or simply passing them to clang and clang is deciding from the file extension - then it would likely not know what ".ipp" means. Does the problem go away if you rename that file to "foo.hpp"? – Casey Jan 21 '14 at 14:39
  • @Casey Thanks for the suggestion, that didn't work though. I got some ideas of things to try by looking at the flycheck github issues and questions. I'll try some and post an update (hopefully as an answer). – mkm Jan 21 '14 at 17:21

0 Answers0