<div>On Mon, Feb 11, 2013 at 3:49 PM, Rafael Espíndola <span dir="ltr"><<a href="mailto:rafael.espindola@gmail.com" target="_blank">rafael.espindola@gmail.com</a>></span> wrote:</div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
The attached patch adds a getLanguageLinkage method that explicit<br>
models the possible language linkages (C, C++, none). This fixes some<br>
cases we were producing wrong answers when a function or variable has<br>
no language linkage. In particular, with this patch we don't warn<br>
anymore in<br>
<br>
extern "C" {<br>
  static NonPod foo();<br>
}<br>
<br>
Checking the linkage when computing the language linkage introduces<br>
two small chalenges:<br>
<br>
* We cannot check the language linkage when computing the linkage.<br>
This was done to decide if we should produce uniqueExternal or not,<br>
and I think just checking the decl context has the desired result.<br>
* We cannot ask for the linkage of a decl before linking it in, which<br>
makes the check for conflicting language linkages a bit asymmetrical.<br>
<br>
This exposes that we are not currently including the language linkage<br>
in the function type. I added a test with a fixme.<br></blockquote><div><div><br></div><div>--- a/include/clang/Basic/Linkage.h</div><div>+++ b/include/clang/Basic/Linkage.h</div><div>@@ -42,6 +42,14 @@ enum Linkage {</div>
<div>   ExternalLinkage</div><div> };</div><div> </div></div><div>+/// \brief Describes the different kinds of language linkage</div><div><div>+/// (C++ [dcl.link]) that an entity may have.</div><div>+enum LanguageLinkage {</div>
<div>+  CLanguageLinkage,</div><div>+  CXXLanguageLinkage,</div><div>+  NoLanguageLinkage</div><div>+};</div></div><div><br></div><div>Is there a reason to keep this separate from LinkageSpecDecl::LanguageIDs?</div><div><br>
</div><div><br></div><div><div>--- a/lib/Sema/SemaDecl.cpp</div><div>+++ b/lib/Sema/SemaDecl.cpp</div><div>@@ -2065,6 +2065,22 @@ static bool isABIDefaultCC(Sema &S, CallingConv CC, FunctionDecl *D) {</div><div>   return ABIDefaultCC == CC;</div>
<div> }</div><div> </div><div>+template<typename T></div><div>+bool haveIncompatibleLanguageLinkages(const T *Old, const T *New) {</div><div>+  const DeclContext *DC = Old->getDeclContext();</div><div>+  if (DC->isRecord())</div>
<div>+    return false;</div><div>+</div><div>+  LanguageLinkage OldLinkage = Old->getLanguageLinkage();</div><div>+  if (OldLinkage == CXXLanguageLinkage &&</div><div>+      New->getDeclContext()->isExternCContext())</div>
<div>+    return true;</div><div>+  if (OldLinkage == CLanguageLinkage &&</div><div>+      New->getDeclContext()->isExternCXXContext())</div><div>+    return true;</div><div>+  return false;</div><div>+}</div>
</div><div><br></div><div>If you use the same enum for language linkage in FunctionDecl/VarDecl and LinkageSpecDecl, you should be able to simplify this a little.</div><div><br></div><div><br></div><div><div>--- a/test/SemaCXX/linkage2.cpp</div>
<div>+++ b/test/SemaCXX/linkage2.cpp</div><div>@@ -2,20 +2,22 @@</div><div> </div><div> namespace test1 {</div><div>   int x; // expected-note {{previous definition is here}}</div><div>-  static int y; // expected-note {{previous definition is here}}</div>
<div>+  static int y;</div><div>   void f() {} // expected-note {{previous definition is here}}</div><div> </div><div>   extern "C" {</div><div>     extern int x; // expected-error {{declaration of 'x' has a different language linkage}}</div>
<div>-    extern int y; // expected-error {{declaration of 'y' has a different language linkage}}</div><div>+    extern int y; // OK, has internal linkage, so no language linkage.</div><div>     void f(); // expected-error {{declaration of 'f' has a different language linkage}}</div>
<div>   }</div><div> }</div><div> </div><div>+// This is OK. Both test2_f don't have language linkage since they have</div><div>+// internal linkage.</div><div> extern "C" {</div><div>-  static void test2_f() { // expected-note {{previous definition is here}}</div>
<div>+  static void test2_f() {</div><div>   }</div><div>-  static void test2_f(int x) { // expected-error {{conflicting types for 'test2_f'}}</div><div>+  static void test2_f(int x) {</div><div>   }</div><div> }</div>
<div><br></div><div>Please add a CodeGen test to ensure that we give these two functions different mangled names.</div><div><br></div></div></div>