Index: include/clang/AST/DeclBase.h =================================================================== --- include/clang/AST/DeclBase.h +++ include/clang/AST/DeclBase.h @@ -1334,6 +1334,9 @@ /// 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; Index: lib/AST/DeclBase.cpp =================================================================== --- lib/AST/DeclBase.cpp +++ lib/AST/DeclBase.cpp @@ -992,6 +992,18 @@ 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(DC)->getLanguage() == + clang::LinkageSpecDecl::lang_c) + return cast(DC); + DC = DC->getLexicalParent(); + } + return nullptr; +} + bool DeclContext::isExternCXXContext() const { return isLinkageSpecContext(this, clang::LinkageSpecDecl::lang_cxx); } Index: lib/Sema/SemaDeclCXX.cpp =================================================================== --- lib/Sema/SemaDeclCXX.cpp +++ lib/Sema/SemaDeclCXX.cpp @@ -12757,6 +12757,9 @@ if (FnDecl->isExternC()) { Diag(FnDecl->getLocation(), diag::err_literal_operator_extern_c); + if (const LinkageSpecDecl *LSD = + FnDecl->getDeclContext()->getExternCContext()) + Diag(LSD->getExternLoc(), diag::note_module_import_in_extern_c); return true; } Index: lib/Sema/SemaTemplate.cpp =================================================================== --- lib/Sema/SemaTemplate.cpp +++ lib/Sema/SemaTemplate.cpp @@ -5939,9 +5939,13 @@ // 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_module_import_in_extern_c); + return true; + } Ctx = Ctx->getRedeclContext(); // C++ [temp]p2: Index: test/CXX/over/over.oper/over.literal/p6.cpp =================================================================== --- test/CXX/over/over.oper/over.literal/p6.cpp +++ 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 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 void operator "" _d(); // expected-error {{must have C++ linkage}} namespace N { Index: test/SemaCXX/cxx0x-defaulted-functions.cpp =================================================================== --- test/SemaCXX/cxx0x-defaulted-functions.cpp +++ test/SemaCXX/cxx0x-defaulted-functions.cpp @@ -180,7 +180,7 @@ Outer::Inner2::~Inner2() = default; // expected-error {{nested name specifier 'Outer::Inner2::' 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 // expected-error {{templates must have C++ linkage}} void PR13573(const _Tp&) = delete; } Index: test/SemaTemplate/class-template-decl.cpp =================================================================== --- test/SemaTemplate/class-template-decl.cpp +++ test/SemaTemplate/class-template-decl.cpp @@ -10,11 +10,11 @@ template class C; } -extern "C" { +extern "C" { // expected-note {{extern "C" language linkage specification begins here}} template 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 class D; // expected-error{{templates must have C++ linkage}} template void f(); // expected-error{{templates must have C++ linkage}} @@ -148,7 +148,7 @@ } extern "C" template // 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; }