[patch] Misc fixes to our handling of language linkage.
Richard Smith
richard at metafoo.co.uk
Mon Feb 11 16:20:00 PST 2013
On Mon, Feb 11, 2013 at 3:49 PM, Rafael EspĂndola <
rafael.espindola at gmail.com> wrote:
> The attached patch adds a getLanguageLinkage method that explicit
> models the possible language linkages (C, C++, none). This fixes some
> cases we were producing wrong answers when a function or variable has
> no language linkage. In particular, with this patch we don't warn
> anymore in
>
> extern "C" {
> static NonPod foo();
> }
>
> Checking the linkage when computing the language linkage introduces
> two small chalenges:
>
> * We cannot check the language linkage when computing the linkage.
> This was done to decide if we should produce uniqueExternal or not,
> and I think just checking the decl context has the desired result.
> * We cannot ask for the linkage of a decl before linking it in, which
> makes the check for conflicting language linkages a bit asymmetrical.
>
> This exposes that we are not currently including the language linkage
> in the function type. I added a test with a fixme.
>
--- a/include/clang/Basic/Linkage.h
+++ b/include/clang/Basic/Linkage.h
@@ -42,6 +42,14 @@ enum Linkage {
ExternalLinkage
};
+/// \brief Describes the different kinds of language linkage
+/// (C++ [dcl.link]) that an entity may have.
+enum LanguageLinkage {
+ CLanguageLinkage,
+ CXXLanguageLinkage,
+ NoLanguageLinkage
+};
Is there a reason to keep this separate from LinkageSpecDecl::LanguageIDs?
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -2065,6 +2065,22 @@ static bool isABIDefaultCC(Sema &S, CallingConv CC,
FunctionDecl *D) {
return ABIDefaultCC == CC;
}
+template<typename T>
+bool haveIncompatibleLanguageLinkages(const T *Old, const T *New) {
+ const DeclContext *DC = Old->getDeclContext();
+ if (DC->isRecord())
+ return false;
+
+ LanguageLinkage OldLinkage = Old->getLanguageLinkage();
+ if (OldLinkage == CXXLanguageLinkage &&
+ New->getDeclContext()->isExternCContext())
+ return true;
+ if (OldLinkage == CLanguageLinkage &&
+ New->getDeclContext()->isExternCXXContext())
+ return true;
+ return false;
+}
If you use the same enum for language linkage in FunctionDecl/VarDecl and
LinkageSpecDecl, you should be able to simplify this a little.
--- a/test/SemaCXX/linkage2.cpp
+++ b/test/SemaCXX/linkage2.cpp
@@ -2,20 +2,22 @@
namespace test1 {
int x; // expected-note {{previous definition is here}}
- static int y; // expected-note {{previous definition is here}}
+ static int y;
void f() {} // expected-note {{previous definition is here}}
extern "C" {
extern int x; // expected-error {{declaration of 'x' has a different
language linkage}}
- extern int y; // expected-error {{declaration of 'y' has a different
language linkage}}
+ extern int y; // OK, has internal linkage, so no language linkage.
void f(); // expected-error {{declaration of 'f' has a different
language linkage}}
}
}
+// This is OK. Both test2_f don't have language linkage since they have
+// internal linkage.
extern "C" {
- static void test2_f() { // expected-note {{previous definition is here}}
+ static void test2_f() {
}
- static void test2_f(int x) { // expected-error {{conflicting types for
'test2_f'}}
+ static void test2_f(int x) {
}
}
Please add a CodeGen test to ensure that we give these two functions
different mangled names.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130211/721fc0b4/attachment.html>
More information about the cfe-commits
mailing list