Author: arphaman
Date: Wed Nov  2 10:46:34 2016
New Revision: 285823

URL: http://llvm.org/viewvc/llvm-project?rev=285823&view=rev
Log:
Add a note that points to the linkage specifier for the C++ linkage errors

This commit improves the "must have C++ linkage" error diagnostics that are
emitted for C++ declarations like templates and literal operators by adding an
additional note that points to the appropriate extern "C" linkage specifier.

rdar://19021120

Differential Revision: https://reviews.llvm.org/D26189

Modified:
    cfe/trunk/include/clang/AST/DeclBase.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/AST/DeclBase.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/test/CXX/over/over.oper/over.literal/p6.cpp
    cfe/trunk/test/SemaCXX/cxx0x-defaulted-functions.cpp
    cfe/trunk/test/SemaTemplate/class-template-decl.cpp

Modified: cfe/trunk/include/clang/AST/DeclBase.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclBase.h?rev=285823&r1=285822&r2=285823&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclBase.h (original)
+++ cfe/trunk/include/clang/AST/DeclBase.h Wed Nov  2 10:46:34 2016
@@ -1334,6 +1334,9 @@ public:
   /// linkage specification context that specifies C linkage.
   bool isExternCContext() const;
 
+  /// \brief Retrieve the nearest enclosing C linkage specification context.
+  const LinkageSpecDecl *getExternCContext() const;
+
   /// \brief Determines whether this context or some of its ancestors is a
   /// linkage specification context that specifies C++ linkage.
   bool isExternCXXContext() const;

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=285823&r1=285822&r2=285823&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Nov  2 10:46:34 
2016
@@ -4502,6 +4502,8 @@ def err_extern_c_global_conflict : Error
   "conflicts with declaration %select{in global scope|with C language 
linkage}0">;
 def note_extern_c_global_conflict : Note<
   "declared %select{in global scope|with C language linkage}0 here">;
+def note_extern_c_begins_here : Note<
+  "extern \"C\" language linkage specification begins here">;
 def warn_weak_import : Warning <
   "an already-declared variable is made a weak_import declaration %0">;
 def ext_static_non_static : Extension<
@@ -8605,8 +8607,6 @@ def ext_module_import_in_extern_c : ExtW
   "import of C++ module '%0' appears within extern \"C\" language linkage "
   "specification">, DefaultError,
   InGroup<DiagGroup<"module-import-in-extern-c">>;
-def note_module_import_in_extern_c : Note<
-  "extern \"C\" language linkage specification begins here">;
 def err_module_import_not_at_top_level_fatal : Error<
   "import of module '%0' appears within %1">, DefaultFatal;
 def ext_module_import_not_at_top_level_noop : ExtWarn<

Modified: cfe/trunk/lib/AST/DeclBase.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=285823&r1=285822&r2=285823&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Wed Nov  2 10:46:34 2016
@@ -992,6 +992,18 @@ bool DeclContext::isExternCContext() con
   return isLinkageSpecContext(this, clang::LinkageSpecDecl::lang_c);
 }
 
+const LinkageSpecDecl *DeclContext::getExternCContext() const {
+  const DeclContext *DC = this;
+  while (DC->getDeclKind() != Decl::TranslationUnit) {
+    if (DC->getDeclKind() == Decl::LinkageSpec &&
+        cast<LinkageSpecDecl>(DC)->getLanguage() ==
+            clang::LinkageSpecDecl::lang_c)
+      return cast<LinkageSpecDecl>(DC);
+    DC = DC->getLexicalParent();
+  }
+  return nullptr;
+}
+
 bool DeclContext::isExternCXXContext() const {
   return isLinkageSpecContext(this, clang::LinkageSpecDecl::lang_cxx);
 }

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=285823&r1=285822&r2=285823&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Nov  2 10:46:34 2016
@@ -15341,7 +15341,7 @@ static void checkModuleImportContext(Sem
   } else if (!M->IsExternC && ExternCLoc.isValid()) {
     S.Diag(ImportLoc, diag::ext_module_import_in_extern_c)
       << M->getFullModuleName();
-    S.Diag(ExternCLoc, diag::note_module_import_in_extern_c);
+    S.Diag(ExternCLoc, diag::note_extern_c_begins_here);
   }
 }
 

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=285823&r1=285822&r2=285823&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Nov  2 10:46:34 2016
@@ -12757,6 +12757,9 @@ bool Sema::CheckLiteralOperatorDeclarati
 
   if (FnDecl->isExternC()) {
     Diag(FnDecl->getLocation(), diag::err_literal_operator_extern_c);
+    if (const LinkageSpecDecl *LSD =
+            FnDecl->getDeclContext()->getExternCContext())
+      Diag(LSD->getExternLoc(), diag::note_extern_c_begins_here);
     return true;
   }
 

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=285823&r1=285822&r2=285823&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed Nov  2 10:46:34 2016
@@ -5939,9 +5939,13 @@ Sema::CheckTemplateDeclScope(Scope *S, T
   // C++ [temp]p4:
   //   A template [...] shall not have C linkage.
   DeclContext *Ctx = S->getEntity();
-  if (Ctx && Ctx->isExternCContext())
-    return Diag(TemplateParams->getTemplateLoc(), diag::err_template_linkage)
-             << TemplateParams->getSourceRange();
+  if (Ctx && Ctx->isExternCContext()) {
+    Diag(TemplateParams->getTemplateLoc(), diag::err_template_linkage)
+        << TemplateParams->getSourceRange();
+    if (const LinkageSpecDecl *LSD = Ctx->getExternCContext())
+      Diag(LSD->getExternLoc(), diag::note_extern_c_begins_here);
+    return true;
+  }
   Ctx = Ctx->getRedeclContext();
 
   // C++ [temp]p2:

Modified: cfe/trunk/test/CXX/over/over.oper/over.literal/p6.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/over/over.oper/over.literal/p6.cpp?rev=285823&r1=285822&r2=285823&view=diff
==============================================================================
--- cfe/trunk/test/CXX/over/over.oper/over.literal/p6.cpp (original)
+++ cfe/trunk/test/CXX/over/over.oper/over.literal/p6.cpp Wed Nov  2 10:46:34 
2016
@@ -1,9 +1,11 @@
 // RUN: %clang_cc1 -std=c++11 %s -verify
 
+// expected-note@+1 {{extern "C" language linkage specification begins here}}
 extern "C" void operator "" _a(const char *); // expected-error {{must have 
C++ linkage}}
 extern "C" template<char...> void operator "" _b(); // expected-error {{must 
have C++ linkage}}
+// expected-note@-1 {{extern "C" language linkage specification begins here}}
 
-extern "C" {
+extern "C" { // expected-note 4 {{extern "C" language linkage specification 
begins here}}
   void operator "" _c(const char *); // expected-error {{must have C++ 
linkage}}
   template<char...> void operator "" _d(); // expected-error {{must have C++ 
linkage}}
   namespace N {

Modified: cfe/trunk/test/SemaCXX/cxx0x-defaulted-functions.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-defaulted-functions.cpp?rev=285823&r1=285822&r2=285823&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx0x-defaulted-functions.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx0x-defaulted-functions.cpp Wed Nov  2 10:46:34 
2016
@@ -180,7 +180,7 @@ namespace PR14577 {
   Outer<T>::Inner2<T>::~Inner2() = default; // expected-error {{nested name 
specifier 'Outer<T>::Inner2<T>::' for declaration does not refer into a class, 
class template or class template partial specialization}}  expected-error 
{{only special member functions may be defaulted}}
 }
 
-extern "C" {
+extern "C" { // expected-note {{extern "C" language linkage specification 
begins here}}
  template<typename _Tp> // expected-error {{templates must have C++ linkage}}
  void PR13573(const _Tp&) = delete;
 }

Modified: cfe/trunk/test/SemaTemplate/class-template-decl.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/class-template-decl.cpp?rev=285823&r1=285822&r2=285823&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/class-template-decl.cpp (original)
+++ cfe/trunk/test/SemaTemplate/class-template-decl.cpp Wed Nov  2 10:46:34 2016
@@ -10,11 +10,11 @@ namespace N {
   template<typename T> class C;
 }
 
-extern "C" {
+extern "C" { // expected-note {{extern "C" language linkage specification 
begins here}}
   template<typename T> class D; // expected-error{{templates must have C++ 
linkage}}
 }
 
-extern "C" {
+extern "C" { // expected-note 2 {{extern "C" language linkage specification 
begins here}}
   class PR17968 {
     template<typename T> class D; // expected-error{{templates must have C++ 
linkage}}
     template<typename T> void f(); // expected-error{{templates must have C++ 
linkage}}
@@ -148,7 +148,7 @@ namespace redecl {
 }
 
 extern "C" template <typename T> // expected-error{{templates must have C++ 
linkage}}
-void DontCrashOnThis() {
+void DontCrashOnThis() { // expected-note@-1 {{extern "C" language linkage 
specification begins here}}
   T &pT = T();
   pT;
 }


_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to