summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Lorenz <arphaman@gmail.com>2016-11-02 15:46:34 +0000
committerAlex Lorenz <arphaman@gmail.com>2016-11-02 15:46:34 +0000
commit560ae565e9fa981ce2a49282b71c1e716ff347d1 (patch)
treee84aeceba2a821f6f863609ac9dd5307da27cb57
parent93f2f7fb6c323083ec39abc0b67a9b51dc416684 (diff)
downloadbcm5719-llvm-560ae565e9fa981ce2a49282b71c1e716ff347d1.tar.gz
bcm5719-llvm-560ae565e9fa981ce2a49282b71c1e716ff347d1.zip
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 llvm-svn: 285823
-rw-r--r--clang/include/clang/AST/DeclBase.h3
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td4
-rw-r--r--clang/lib/AST/DeclBase.cpp12
-rw-r--r--clang/lib/Sema/SemaDecl.cpp2
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp3
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp10
-rw-r--r--clang/test/CXX/over/over.oper/over.literal/p6.cpp4
-rw-r--r--clang/test/SemaCXX/cxx0x-defaulted-functions.cpp2
-rw-r--r--clang/test/SemaTemplate/class-template-decl.cpp6
9 files changed, 35 insertions, 11 deletions
diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h
index 3a80ff5b234..5de1d0588e8 100644
--- a/clang/include/clang/AST/DeclBase.h
+++ b/clang/include/clang/AST/DeclBase.h
@@ -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;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index e4290d8945a..74fed48806a 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -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 : ExtWarn<
"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<
diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp
index 7e790cec68a..5d130acfbed 100644
--- a/clang/lib/AST/DeclBase.cpp
+++ b/clang/lib/AST/DeclBase.cpp
@@ -992,6 +992,18 @@ bool DeclContext::isExternCContext() const {
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);
}
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 1813aa0b648..e20ae1a0151 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -15341,7 +15341,7 @@ static void checkModuleImportContext(Sema &S, Module *M,
} 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);
}
}
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 17d1978de03..fb3b7373978 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -12757,6 +12757,9 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) {
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;
}
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 71b2153d05a..ce41a5eb74f 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -5939,9 +5939,13 @@ Sema::CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams) {
// 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:
diff --git a/clang/test/CXX/over/over.oper/over.literal/p6.cpp b/clang/test/CXX/over/over.oper/over.literal/p6.cpp
index 6bfb8560d68..9ecf9ccccb1 100644
--- a/clang/test/CXX/over/over.oper/over.literal/p6.cpp
+++ b/clang/test/CXX/over/over.oper/over.literal/p6.cpp
@@ -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 {
diff --git a/clang/test/SemaCXX/cxx0x-defaulted-functions.cpp b/clang/test/SemaCXX/cxx0x-defaulted-functions.cpp
index f4bbce818d9..f623dc765f8 100644
--- a/clang/test/SemaCXX/cxx0x-defaulted-functions.cpp
+++ b/clang/test/SemaCXX/cxx0x-defaulted-functions.cpp
@@ -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;
}
diff --git a/clang/test/SemaTemplate/class-template-decl.cpp b/clang/test/SemaTemplate/class-template-decl.cpp
index 63482d84df0..2e36cae14f6 100644
--- a/clang/test/SemaTemplate/class-template-decl.cpp
+++ b/clang/test/SemaTemplate/class-template-decl.cpp
@@ -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;
}
OpenPOWER on IntegriCloud