Page MenuHomePhabricator

[Sema] Diagnose template specializations with C linkage
Needs ReviewPublic

Authored by miyuki on Dec 13 2017, 5:54 AM.

Details

Summary

[Sema] Diagnose template specializations with C linkage

According to the C++ standard, templates as well as their
specializations cannot have C language linkage. Clang currently does
not diagnose function template specializations and class template
specializations with C linkage.

This patch implements such a diagnostic and adds tests for it.

Diff Detail

Event Timeline

miyuki created this revision.Dec 13 2017, 5:54 AM
rogfer01 added inline comments.Dec 13 2017, 8:32 AM
lib/Sema/SemaTemplate.cpp
7087

Can you add a test for a partial specialization? Your test for the class case only includes an explicit specialization.

template <typename T>
struct A { };

extern "C" { 

template <typename T>   // I'd expect a diagnostic around here
struct A<T*>
{
};

}
miyuki added inline comments.Dec 13 2017, 10:14 AM
lib/Sema/SemaTemplate.cpp
7087

Currently the location used for template specialization-related diagnostics is on the next line, e.g.:

/work/llvm/src/tools/clang/test/SemaTemplate/class-template-spec.cpp:242:10: error: templates must have C++ linkage
  struct C<T*> {};
         ^

Do we want to use a different location for this particular diagnostic?

rogfer01 added inline comments.Dec 13 2017, 11:34 AM
lib/Sema/SemaTemplate.cpp
7087

Oh sorry, I was not precise when I put that example. I don't think it should be different in this case.

miyuki updated this revision to Diff 126915.Dec 14 2017, 2:03 AM

Added a test for partial specialization.

miyuki marked an inline comment as done.Dec 14 2017, 2:03 AM
faisalv added inline comments.Dec 17 2017, 7:58 PM
lib/Sema/SemaTemplate.cpp
7095

What do you think about factoring this out into a separate function that is then called both from here and CheckTemplateDeclScope (since it is exactly the same code?)

Is it correct to emit error in this case?

According to the Standard 10.5p1 "All function types, function names with external linkage, and variable names with external linkage have a language linkage". So templates do not have a language linkage.
The next paragraph, which introduces inkage-specification, states: "The string-literal indicates the required language linkage". So the construct extern "C" specifies just language linkage, which is not pertinent to templates.

In 10.5p4 there is an example of a class defined in extern "C" construct:

extern "C" {
  class X {
    void mf(); // the name of the function mf and the member function’s type have
               // C++ language linkage
    void mf2(void(*)()); // the name of the function mf2 has C++ language linkage;
                         // the parameter has type “pointer to C function”
  };
}

Classes do not have language linkage according to 10.5p1, just as templates, so this code is valid.

It looks like defining templates inside extern "C" blocks is OK.

miyuki updated this revision to Diff 128234.Dec 27 2017, 7:05 AM

Factored out template language linkage check into a separate function

miyuki marked an inline comment as done.Dec 27 2017, 7:07 AM
Classes do not have language linkage according to 10.5p1, just as templates, so this code is valid.

It looks like defining templates inside extern "C" blocks is OK.

Currently both Clang and GCC diagnose class templates declared inside an 'extern "C"' block. I'm not sure how to proceed about this.

Classes do not have language linkage according to 10.5p1, just as templates, so this code is valid.

It looks like defining templates inside extern "C" blocks is OK.

Currently both Clang and GCC diagnose class templates declared inside an 'extern "C"' block. I'm not sure how to proceed about this.

Given that Clause 17 p6 specifically uses 'shall' to call out templates - i believe the implementation is expected to diagnose this. 10.5p1 (or is there another mention in the standard?) does not explicitly call out 'classes' as not having c language linkage - so implementations can get away not diagnosing this - and perhaps even allow classes to have language linkage on certain implementations?? (at least that's my squinty interpretation)

Classes do not have language linkage according to 10.5p1, just as templates, so this code is valid.

It looks like defining templates inside extern "C" blocks is OK.

Currently both Clang and GCC diagnose class templates declared inside an 'extern "C"' block. I'm not sure how to proceed about this.

Given that Clause 17 p6 specifically uses 'shall' to call out templates - i believe the implementation is expected to diagnose this. 10.5p1 (or is there another mention in the standard?) does not explicitly call out 'classes' as not having c language linkage - so implementations can get away not diagnosing this - and perhaps even allow classes to have language linkage on certain implementations?? (at least that's my squinty interpretation)

This is a strange clause. The language linkage describes cases when an entity defined in one TU is identical to another entity in another TU implemented in different language. As templates have no meaning outside C++, so they merely cannot have C linkage.

I guess the statement about C linkage in 17p6 is a remnant of those times when template were allowed to have export specifier. In that case templates would have external representation and in principle could be used in non C++ compilation.

Maybe @rsmith could clarify this point?