Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fix a -Wsubobject-linkage warning?

Tags:

c++

c++11

I'm getting a gcc warning for code which compiles fine and warning free in clang and VC++, so I assume it's something gcc specific. This is the code:

namespace myns {
  using TokenList = std::vector<size_t>;
  using RuleList = std::vector<size_t>;
  using RulePathPair = std::pair<size_t, TokenList>;
  using CandidatesCollection = struct { std::map<size_t, TokenList> tokens; std::set<RulePathPair> rules; };

  class A {
  private:
    CandidatesCollection _candidates;
  };
} // namespace myns

and the warning is:

warning: 'myns::A' has a field 'myns::A::_candidates' whose type has no linkage [-Wsubobject-linkage]

What does this mean and how to get rid of the warning?

like image 338
Mike Lischke Avatar asked Dec 15 '16 14:12

Mike Lischke


1 Answers

I believe the compiler might be wrong here: the type referred to by CandidatesCollection should in fact have external linkage.

[basic.link]/4 ...A name having namespace scope that has not been given internal linkage above has the same linkage as the enclosing namespace if it is the name of

...

(4.3) — a named class (Clause 9), or an unnamed class defined in a typedef declaration in which the class has the typedef name for linkage purposes (7.1.3); ...


[dcl.typedef]/9 If the typedef declaration defines an unnamed class (or enum), the first typedef-name declared by the declaration to be that class type (or enum type) is used to denote the class type (or enum type) for linkage purposes only (3.5). [ Example:

 typedef struct { } *ps, S; // S is the class name for linkage purposes

—end example ]

Thus, if CandidatesCollection were defined as

typedef struct { ... } CandidatesCollection;

these two passages make it clear that the class named by CandidatesCollection would happily have external linkage.

Then there's

[dcl.typedef]/2 A typedef-name can also be introduced by an alias-declaration. The identifier following the using keyword becomes a typedef-name and the optional attribute-specifier-seq following the identifier appertains to that typedef-name. It has the same semantics as if it were introduced by the typedef specifier.

Emphasis mine. This suggests that the name introduced by using should give the unnamed class "the name for linkage purposes" just as well as the equivalent typedef declaration, thereby ensuring that the class has external linkage.

like image 80
Igor Tandetnik Avatar answered Oct 18 '22 14:10

Igor Tandetnik