This is an archive of the discontinued LLVM Phabricator instance.

MSVC compat: Allow lookup of friend types in enclosing namespaces
ClosedPublic

Authored by rnk on Jul 9 2014, 3:32 PM.

Details

Summary

The relevant portion of C++ standard says [namespace.memdef]p3:

If the name in a friend declaration is neither qualified nor a
template-id and the declaration is a function or an
elaborated-type-specifier, the lookup to determine whether the entity
has been previously declared shall not consider any scopes outside the
innermost enclosing namespace.

MSVC does not implement that rule for types. If there is a type in an
enclosing namespace, they consider an unqualified tag declaration with
the same name to be a redeclaration of the type from another namespace.

Implementing compatibility is a simple matter of disabling our
implementation of this rule for types, which was added in r177473.

Diff Detail

Repository
rL LLVM

Event Timeline

rnk updated this revision to Diff 11226.Jul 9 2014, 3:32 PM
rnk retitled this revision from to MSVC compat: Allow lookup of friend types in enclosing namespaces.
rnk updated this object.
rnk added reviewers: rsmith, doug.gregor.
rnk added a subscriber: Unknown Object (MLST).
rsmith added inline comments.Jul 9 2014, 5:04 PM
include/clang/Basic/DiagnosticSemaKinds.td
1000–1002 ↗(On Diff #11226)

Please add a bit more information here: which NNS should be added? What is the enclosing namespace that we looked in? Which type did we actually find? A fixit adding the NNS would help.

1001 ↗(On Diff #11226)

Singular/plural mismatch ("declarations ... is a MS extension"). Please make this singular.

1002 ↗(On Diff #11226)

Maybe drop the "to fix"?

lib/Sema/SemaDecl.cpp
11467 ↗(On Diff #11226)

This was a prior attempt to get ~half of the same effect. In particular, for:

struct X {};
namespace N {
  struct Y { friend struct X; };
  X x;
}

... we need to not inject X into N, or the lookup for N::x's type will find the wrong struct.

Perhaps we should remove this hack (for MicrosoftExt) now that we have a more faithful hack (for MSVCCompat)? It's not a conforming extension. That is, replace this with just

New->setObjectOfFriendDecl(getLangOpts().MSVCCompat);
rnk added inline comments.Jul 10 2014, 2:40 PM
include/clang/Basic/DiagnosticSemaKinds.td
1000–1002 ↗(On Diff #11226)

Done. It's a very nice diagnostic now, although maybe this is overkill for a fairly pedantic portion of the standard where implementations disagree. :)

1001 ↗(On Diff #11226)

done

1002 ↗(On Diff #11226)

done

lib/Sema/SemaDecl.cpp
11467 ↗(On Diff #11226)

I agree, I'd rather have just one faithful hack, but presumably Doug put this under -fms-extensions for a reason. Hopefully we can raise him. :)

I'll make the change, since I think we both agree this shouldn't be under -fms-extensions.

rnk updated this revision to Diff 11296.Jul 10 2014, 3:02 PM
  • add a super awesome fixit
rsmith accepted this revision.Jul 10 2014, 3:35 PM
rsmith edited edge metadata.

LGTM

lib/Sema/SemaDecl.cpp
10740 ↗(On Diff #11296)

Stray 'something'?

10986 ↗(On Diff #11296)

auto?

This revision is now accepted and ready to land.Jul 10 2014, 3:35 PM
rnk closed this revision.Jul 10 2014, 4:53 PM
rnk updated this revision to Diff 11301.

Closed by commit rL212784 (authored by @rnk).

rnk added inline comments.Jul 10 2014, 4:59 PM
lib/Sema/SemaDecl.cpp
10740 ↗(On Diff #11296)

yeah

10986 ↗(On Diff #11296)

It used to be auto, but I had to feed it into addFriendTagNNSFixIt, so I made it explicit. I guess I can flip it back.

rsmith added inline comments.Jul 10 2014, 5:07 PM
lib/Sema/SemaDecl.cpp
10986 ↗(On Diff #11296)

Maybe either make addFriendTagNNSFixIt take a DiagnosticBuilder& so it doesn't need to care about this, or make it return a FixItHint? (A default-constructed FixItHint will be ignored by the diagnostic renderer.)

rnk added inline comments.Jul 10 2014, 5:25 PM
lib/Sema/SemaDecl.cpp
10986 ↗(On Diff #11296)

I considered that, but FixItHint::CreateInsertion takes a StringRef, so I didn't think I could safely return one without UAF bugs. Looks like it uses a std::string for storage, so it all works out. Done in r212786.