Skip to content

clang-cl treats different extern "C" declarations as redeclarations #29512

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
arrowd opened this issue Aug 25, 2016 · 5 comments
Closed

clang-cl treats different extern "C" declarations as redeclarations #29512

arrowd opened this issue Aug 25, 2016 · 5 comments
Labels
bugzilla Issues migrated from bugzilla c++ clang:frontend Language frontend issues, e.g. anything involving "Sema" duplicate Resolved as duplicate platform:windows

Comments

@arrowd
Copy link
Contributor

arrowd commented Aug 25, 2016

Bugzilla Link 29142
Version 3.9
OS Windows NT
CC @DougGregor,@zygoloid,@rnk

Extended Description

The code

namespace acommon {

struct ErrorInfo;

extern "C" __declspec(dllexport)  const ErrorInfo * const aerror_other;

}

extern "C" {
struct AspellErrorInfo {

  const struct AspellErrorInfo * isa;

  const char * mesg;

  unsigned int num_parms;

  const char * parms[3];

};


typedef struct AspellErrorInfo AspellErrorInfo;
extern const struct AspellErrorInfo * const aerror_other;
}

int main()
{
return 0;
}

compiles with cl.exe, but fails with clang-cl.exe:

tst.cpp(25,45):  error: redeclaration of 'aerror_other' with a different type: 'const struct AspellErrorInfo *const' vs 'const acommon::ErrorInfo *const'
extern const struct AspellErrorInfo * const aerror_other;
                                            ^
tst.cpp(6,59):  note: previous declaration is here
extern "C" __declspec(dllexport)  const ErrorInfo * const aerror_other;
                                                          ^
@rnk
Copy link
Collaborator

rnk commented Aug 25, 2016

MSVC's model doesn't make sense. They accept this code and generate an object file with two bar symbols:

namespace foo { extern "C" int bar = 1; }
extern "C" int bar = 2;

Your code looks more like this:

namespace foo { extern "C" int bar = 1; }
int bar = 2;

... which doesn't produce an invalid object with MSVC, so it's not obviously invalid.

I suspect that that code is ill-formed, though. If you can make the case that there is a large body of existing code with this issue, we might find a way to accept this pattern. Otherwise my inclination is to say that this is working as intended.

@arrowd
Copy link
Contributor Author

arrowd commented Aug 25, 2016

MSVC's model doesn't make sense. They accept this code and generate an
object file with two "bar" symbols:

namespace foo { extern "C" int bar = 1; }
extern "C" int bar = 2;

Your code looks more like this:

namespace foo { extern "C" int bar = 1; }
int bar = 2;

... which doesn't produce an invalid object with MSVC, so it's not obviously
invalid.

I suspect that that code is ill-formed, though. If you can make the case
that there is a large body of existing code with this issue, we might find a
way to accept this pattern. Otherwise my inclination is to say that this is
working as intended.

Well, this is what i get when i try to compile aspell (as you might guessed) on Windows. I can't judge which compiler is right, so feel free to close this bug if you think that clang does right thing.

@zygoloid
Copy link
Mannequin

zygoloid mannequin commented Aug 25, 2016

Because both declarations of aerror_other are declared in extern "C" contexts, they are redeclarations of the same variable; see [dcl.link]/6:

Two declarations for a variable with C language linkage with the same name (ignoring the namespace names that qualify it) that appear in different namespace scopes refer to the same variable.

So this is definitely ill-formed, because the same variable has been declared with two different types, just as it would be if both declarations were in the same namespace. (Most of the other extern "C" rules exist to allow for various name mangling patterns, and we could reasonably relax those for MSVC in cases where the relevant mangling collisions don't occur, but accepting this case seems much less reasonable.)

Note that this isn't only a problem on Windows; aspell's headers are apparently just broken when included from C++:

http://stackoverflow.com/questions/25395685/aspell-wont-build-on-os-x-10-9-mavericks

@llvmbot llvmbot transferred this issue from llvm/llvm-bugzilla-archive Dec 10, 2021
@Endilll Endilll changed the title clang-cl treats different extern "C" declarations as redeclarations clang-cl treats different extern "C" declarations as redeclarations Jul 25, 2024
@Endilll Endilll added platform:windows clang:to-be-triaged Should not be used for new issues labels Jul 25, 2024
@AaronBallman AaronBallman added the duplicate Resolved as duplicate label Jul 26, 2024
@AaronBallman
Copy link
Collaborator

Duplicate of #95681

@AaronBallman AaronBallman marked this as a duplicate of #95681 Jul 26, 2024
@AaronBallman AaronBallman closed this as not planned Won't fix, can't repro, duplicate, stale Jul 26, 2024
@EugeneZelenko EugeneZelenko added clang:frontend Language frontend issues, e.g. anything involving "Sema" and removed clang:to-be-triaged Should not be used for new issues labels Jul 26, 2024
@llvmbot
Copy link
Member

llvmbot commented Jul 26, 2024

@llvm/issue-subscribers-clang-frontend

Author: Gleb Popov (arrowd)

| | | | --- | --- | | Bugzilla Link | [29142](https://llvm.org/bz29142) | | Version | 3.9 | | OS | Windows NT | | CC | @DougGregor,@zygoloid,@rnk |

Extended Description

The code

namespace acommon {

struct ErrorInfo;

extern "C" __declspec(dllexport)  const ErrorInfo * const aerror_other;

}

extern "C" {
struct AspellErrorInfo {

  const struct AspellErrorInfo * isa;

  const char * mesg;

  unsigned int num_parms;

  const char * parms[3];

};


typedef struct AspellErrorInfo AspellErrorInfo;
extern const struct AspellErrorInfo * const aerror_other;
}

int main()
{
return 0;
}

compiles with cl.exe, but fails with clang-cl.exe:

tst.cpp(25,45):  error: redeclaration of 'aerror_other' with a different type: 'const struct AspellErrorInfo *const' vs 'const acommon::ErrorInfo *const'
extern const struct AspellErrorInfo * const aerror_other;
                                            ^
tst.cpp(6,59):  note: previous declaration is here
extern "C" __declspec(dllexport)  const ErrorInfo * const aerror_other;
                                                          ^

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugzilla Issues migrated from bugzilla c++ clang:frontend Language frontend issues, e.g. anything involving "Sema" duplicate Resolved as duplicate platform:windows
Projects
None yet
Development

No branches or pull requests

6 participants