[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