hintonda updated this revision to Diff 48617.
hintonda added a comment.

- Fix remaining test failures caused by linkage errors.


http://reviews.llvm.org/D17362

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/Sema/SemaDecl.cpp
  test/CXX/drs/dr3xx.cpp
  test/Sema/pr23090-crash-on-invalid.cpp
  test/SemaCXX/linkage.cpp
  test/SemaCXX/warn-unused-filescoped.cpp

Index: test/SemaCXX/warn-unused-filescoped.cpp
===================================================================
--- test/SemaCXX/warn-unused-filescoped.cpp
+++ test/SemaCXX/warn-unused-filescoped.cpp
@@ -121,7 +121,6 @@
   namespace { struct A {}; }
 
   void test(A a); // expected-warning {{unused function}}
-  extern "C" void test4(A a);
 }
 
 namespace rdar8733476 {
Index: test/SemaCXX/linkage.cpp
===================================================================
--- test/SemaCXX/linkage.cpp
+++ test/SemaCXX/linkage.cpp
@@ -57,43 +57,21 @@
 
 namespace test3 {
   namespace { struct A {}; }
+  struct B {};
 
   // CHECK: define internal void @_ZN5test34testENS_12_GLOBAL__N_11AE(
   void test(A a) {}
   void force() { test(A()); }
 
   // CHECK: define void @test3(
-  extern "C" void test3(A a) {}
+  extern "C" void test3(B b) {}
 }
 
 namespace {
   // CHECK: define void @test4(
   extern "C" void test4(void) {}
 }
 
-// PR9316: Ensure that even non-namespace-scope function declarations in
-// a C declaration context respect that over the anonymous namespace.
-extern "C" {
-  namespace {
-    struct X {
-      int f() {
-        extern int g();
-        extern int a;
-
-        // Test both for mangling in the code generation and warnings from use
-        // of internal, undefined names via -Werror.
-        // CHECK: call i32 @g(
-        // CHECK: load i32, i32* @a,
-        return g() + a;
-      }
-    };
-  }
-  // Force the above function to be emitted by codegen.
-  int test(X& x) {
-    return x.f();
-  }
-}
-
 // CHECK: define linkonce_odr i8* @_ZN5test11A3fooILj0EEEPvv(
 // CHECK: define linkonce_odr i8* @_ZN5test21A1BILj0EE3fooEv(
 
Index: test/Sema/pr23090-crash-on-invalid.cpp
===================================================================
--- /dev/null
+++ test/Sema/pr23090-crash-on-invalid.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// Don't crash (PR23090).
+
+namespace {
+
+// check return type
+struct A;
+extern "C" A *foo(); // expected-error {{'foo' has C-linkage specified, but return type '(anonymous namespace)::A *' has internal linkage}}
+A *foo();
+
+// check parameter
+struct B;
+extern "C" void bar(B*); // expected-error {{'bar' has C-linkage specified, but parameter type '(anonymous namespace)::B *' has internal linkage}}
+void bar(B*);
+
+}
Index: test/CXX/drs/dr3xx.cpp
===================================================================
--- test/CXX/drs/dr3xx.cpp
+++ test/CXX/drs/dr3xx.cpp
@@ -232,8 +232,8 @@
   typedef struct {
     int i;
   } *ps;
-  extern "C" void f(ps);
-  void g(ps); // FIXME: ill-formed, type 'ps' has no linkage
+  extern "C" void f(ps); // expected-error-re {{'f' has C-linkage specified, but parameter type 'ps' (aka 'dr319::(anonymous struct {{.*}} *') has internal linkage}}
+  void g(ps);
 
   static enum { e } a1;
   enum { e2 } a2; // FIXME: ill-formed, enum type has no linkage
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -8218,6 +8218,25 @@
       Diag(NewFD->getLocation(), diag::ext_out_of_line_declaration)
         << D.getCXXScopeSpec().getRange();
     }
+
+    if (NewFD->isExternC()) {
+      // Check return type linkage
+      QualType R = NewFD->getReturnType();
+      if (R.getTypePtr()->getLinkage() != Linkage::ExternalLinkage) {
+        Diag(NewFD->getLocation(), diag::err_return_value_linkage)
+          << NewFD << R;
+        NewFD->setInvalidDecl();
+      }
+      // Check parameter type linkage
+      for (auto param : NewFD->parameters()) {
+        QualType P = param->getOriginalType();
+        if (P.getTypePtr()->getLinkage() != Linkage::ExternalLinkage) {
+          Diag(NewFD->getLocation(), diag::err_parameter_value_linkage)
+            << NewFD << P;
+          NewFD->setInvalidDecl();
+        }
+      }
+    }
   }
 
   ProcessPragmaWeak(S, NewFD);
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -325,6 +325,11 @@
 def warn_unused_private_field: Warning<"private field %0 is not used">,
   InGroup<UnusedPrivateField>, DefaultIgnore;
 
+def err_return_value_linkage: Error<
+  "%0 has C-linkage specified, but return type %1 has internal linkage">;
+def err_parameter_value_linkage: Error<
+  "%0 has C-linkage specified, but parameter type %1 has internal linkage">;
+
 def warn_parameter_size: Warning<
   "%0 is a large (%1 bytes) pass-by-value argument; "
   "pass it by reference instead ?">, InGroup<LargeByValueCopy>;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to