'Use of undeclared identifier' error using Clang in a C++ project
Asked Answered
B

0

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.

Briseno answered 21/1, 2014 at 11:53 Comment(12)
Try putting the definition in "namespace testnamespace {" ... "}", instead of adding "testnamespace::" on the name.Discrepant
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.Lir
@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)Briseno
@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.Lir
@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?Briseno
@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.Lir
$ clang --version gives: Ubuntu clang version 3.0-6ubuntu3 (tags/RELEASE_30/final) (based on LLVM 3.0)Briseno
@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.Briseno
@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).Lir
@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...Briseno
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"?Maybellmaybelle
@Maybellmaybelle 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).Briseno

© 2022 - 2024 — McMap. All rights reserved.