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