This is an archive of the discontinued LLVM Phabricator instance.

Model type attributes as regular Attrs
ClosedPublic

Authored by rsmith on Aug 9 2018, 12:18 PM.

Details

Summary

Specifically, AttributedType now tracks a regular attr::Kind rather than having its own parallel Kind enumeration, and AttributedTypeLoc now holds an Attr* instead of holding an ad-hoc collection of fields mirroring those that would be present in the corresponding Attr subclass.

This aims to simplify and unify the modeling of attributes, both to make tooling simpler and to avoid code duplication for attributes that can be both type and declaration attributes.

Diff Detail

Repository
rC Clang

Event Timeline

rsmith created this revision.Aug 9 2018, 12:18 PM

Thank you for working on this -- the approach you've taken looks good, and I mostly have little nits here and there. I think this is a great refactoring overall though -- much needed!

include/clang/AST/Type.h
1875

Typo: MRC should be ARC (typo was present in the original code).

include/clang/Basic/Attr.td
1515

I don't suppose you can throw in some quick docs for this keyword? Or is this not really user-facing? If it's not user-facing, perhaps it should have no spellings and only ever be created implicitly?

lib/AST/Type.cpp
1624

const auto *

3215

Probably need to keep this to prevent MSVC from barking about not all control paths returning a value.

3652

Update the identifiers for coding standards since you're basically rewriting the function?

3652–3655

const auto *

lib/AST/TypeLoc.cpp
407–411

Might as well go with const Attr * here, the auto gets us nothing.

lib/Sema/SemaDecl.cpp
6002

const auto *

lib/Sema/SemaType.cpp
178–180

"We use the keep the attributes" isn't grammatical. Should it be, "We keep the attributes in creation order" instead?

181

It's unfortunate to use the name TypeAttr here -- unqualified uses of the type name, like below, makes it look like it might be the TypeAttr from Attr.h

3882

Did clang-format do this? It seems like it's not formatted how I'd expect.

6355

MSVC may complain about not all control paths returning a value here.

lib/Serialization/ASTReaderDecl.cpp
2685–2716

Identifiers don't meet coding style rules.

2701

This could use a comment to explain why the -1 is required. Also, do we have a preference for C-style vs static_cast here?

lib/Serialization/ASTWriter.cpp
4485–4486

llvm::for_each(Attrs, AddAttr); ?

rsmith updated this revision to Diff 160207.Aug 10 2018, 4:45 PM
rsmith marked 10 inline comments as done.
rsmith added inline comments.Aug 10 2018, 4:50 PM
include/clang/Basic/Attr.td
1515

This isn't actually the primary representation of __unsafe_unretained, this is an internal placeholder for "the user wrote __unsafe_unretained but we're not in ARC mode so it's meaningless (hence "inert")". So I don't think this is where we should attach the documentation (the right place is the ObjCOwnership attribute, which is also currently Undocumented, sadly). I'll at least add a comment to the .td file to explain that.

lib/AST/Type.cpp
1624

Done, but...

The pointee type is deduced as const anyway, so the const doesn't give any extra type safety. So the only benefit would be to the reader, and I don't think a reader of this code would care whether *AT is mutable, so the const seems like a distraction to me (and hence the explicit const is a minor harm to readability rather than a minor improvement). I can see how a reader trained to think that absence-of-const implies that mutation is intended would find the explicit const clearer, but (for better or probably worse) that's not the style we generally use in Clang (for instance, I didn't mark the AK parameter as const, but there is no implication that I intend to modify it).

That said, I don't feel strongly about this, and I certainly have no objection to making the change here. If we generally want to move to a style where auto is always accompanied by an explicit const when const would be deduced (in much the same way that we already expect that auto be accompanied by an explicit * when a pointer type would be deduced), I'd be OK with that -- but we should discuss that somewhere more visible than this review thread and include it in our general coding guidelines.

3215

There's a default: case now, so that shouldn't be a problem. (Removing the exhaustive list is intended to be temporary; I'd like to move to generating this with TableGen sooner rather than later.)

lib/Sema/SemaType.cpp
178–180

Hah, oops, yes.

181

Good point. I went with TypeAttrPair here, and AttrsForTypes in the vector.

3882

How would you expect it? clang-format puts a space after the template keyword, unfortunately, and IIRC can't be configured to not do so. Though as a consequence, it looks like the space is now more common in clang code by a 2:1 ratio despite being "clearly wrong" ;-(

6355

I'm confident that this pattern is fine; we use it all over the place. MSVC knows that control flow cannot leave an llvm_unreachable(...).

lib/Serialization/ASTReaderDecl.cpp
2685–2716

Fixed. (This was pre-existing, but I changed everything else in the function.)

lib/Serialization/ASTWriter.cpp
4485–4486

AddAttr is a non-static member function, so that doesn't work; the closest we can get would be something like llvm::for_each(Attrs, [&](const Attr *A) { AddAttr(A); }); -- but that seems unnecessarily circumlocutory to me.

aaron.ballman accepted this revision.Aug 12 2018, 8:00 AM

LGTM! Thank you for this fantastic work!

include/clang/Basic/Attr.td
1515

Ah, thank you for the explanation; I agree.

lib/AST/Type.cpp
1624

That said, I don't feel strongly about this, and I certainly have no objection to making the change here. If we generally want to move to a style where auto is always accompanied by an explicit const when const would be deduced (in much the same way that we already expect that auto be accompanied by an explicit * when a pointer type would be deduced), I'd be OK with that -- but we should discuss that somewhere more visible than this review thread and include it in our general coding guidelines.

Yeah, I actually thought this already was part of the coding guidelines, truth be told. But I went and looked again and realized we only talk about * and & being deduced, not qualifiers. I guess my preference has always been to explicitly spell out pertinent information about the type beyond the name, such as whether it's const, whether it's a pointer, etc. Basically, things that aren't immediately obvious from the context.

I prefer being explicit about spelling out the const here because it makes it obvious that the type is not intended to be mutated, but I only really care about it in cases where the type is deduced to a pointer or reference (and so mutating operations might be hidden behind a function call that looks harmless).

Perhaps this is worth starting a coding guideline discussion over?

lib/Sema/SemaType.cpp
3882

I was expecting to see a space after template as I thought that was the most common form of it in the code base. :-D

6355

Yeah, I think I was mis-remembering a pattern that caused warnings in MSVC here.

lib/Serialization/ASTWriter.cpp
4485–4486

Yeah, that's a bridge too far. The current form is preferable.

This revision is now accepted and ready to land.Aug 12 2018, 8:00 AM
This revision was automatically updated to reflect the committed changes.
rsmith marked an inline comment as done.
rnk added a subscriber: rnk.Aug 13 2018, 6:45 PM

I suspect that somehow this change broke compiling ATL:
https://ci.chromium.org/buildbot/chromium.clang/ToTWin64%28dbg%29/993
https://logs.chromium.org/v/?s=chromium%2Fbb%2Fchromium.clang%2FToTWin64_dbg_%2F995%2F%2B%2Frecipes%2Fsteps%2Fcompile%2F0%2Flogs%2Fraw_io.output_failure_summary_%2F0

Now we get these diagnostics:

[1011/50166] CXX obj/chrome/chrome_cleaner/http/http/error_utils.obj
FAILED: obj/chrome/chrome_cleaner/http/http/error_utils.obj
...
In file included from ../../chrome/chrome_cleaner/http/error_utils.cc:11:
In file included from ../..\base/win/atl.h:18:
In file included from ..\..\third_party\depot_tools\win_toolchain\vs_files\3bc0ec615cf20ee342f3bc29bc991b5ad66d8d2c\VC\Tools\MSVC\14.14.26428\atlmfc\include\atlctl.h:33:
In file included from ..\..\third_party\depot_tools\win_toolchain\vs_files\3bc0ec615cf20ee342f3bc29bc991b5ad66d8d2c\VC\Tools\MSVC\14.14.26428\atlmfc\include\atlwin.h:5107:
..\..\third_party\depot_tools\win_toolchain\vs_files\3bc0ec615cf20ee342f3bc29bc991b5ad66d8d2c\VC\Tools\MSVC\14.14.26428\atlmfc\include\atlhost.h(2777,9):  error: no matching function for call to 'AtlAxDialogCreateT'
return AtlAxDialogCreateT<LPCWSTR, _AtlDialogBoxIndirectParamHelper, ::DialogBoxIndirectParamW>(
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
..\..\third_party\depot_tools\win_toolchain\vs_files\3bc0ec615cf20ee342f3bc29bc991b5ad66d8d2c\VC\Tools\MSVC\14.14.26428\atlmfc\include\atlhost.h(2715,29):  note: candidate template ignored: invalid explicitly-specified argument for template parameter 'pFunc'
typename Helper::ReturnType AtlAxDialogCreateT(
^
..\..\third_party\depot_tools\win_toolchain\vs_files\3bc0ec615cf20ee342f3bc29bc991b5ad66d8d2c\VC\Tools\MSVC\14.14.26428\atlmfc\include\atlhost.h(2788,9):  error: no matching function for call to 'AtlAxDialogCreateT'
return AtlAxDialogCreateT<LPCSTR, _AtlDialogBoxIndirectParamHelper, ::DialogBoxIndirectParamA>(
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
..\..\third_party\depot_tools\win_toolchain\vs_files\3bc0ec615cf20ee342f3bc29bc991b5ad66d8d2c\VC\Tools\MSVC\14.14.26428\atlmfc\include\atlhost.h(2715,29):  note: candidate template ignored: invalid explicitly-specified argument for template parameter 'pFunc'
typename Helper::ReturnType AtlAxDialogCreateT(
^
..\..\third_party\depot_tools\win_toolchain\vs_files\3bc0ec615cf20ee342f3bc29bc991b5ad66d8d2c\VC\Tools\MSVC\14.14.26428\atlmfc\include\atlhost.h(2799,9):  error: no matching function for call to 'AtlAxDialogCreateT'
return AtlAxDialogCreateT<LPCWSTR, _AtlCreateDialogIndirectParamHelper, CreateDialogIndirectParamW>(
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
..\..\third_party\depot_tools\win_toolchain\vs_files\3bc0ec615cf20ee342f3bc29bc991b5ad66d8d2c\VC\Tools\MSVC\14.14.26428\atlmfc\include\atlhost.h(2715,29):  note: candidate template ignored: invalid explicitly-specified argument for template parameter 'pFunc'
typename Helper::ReturnType AtlAxDialogCreateT(
^
..\..\third_party\depot_tools\win_toolchain\vs_files\3bc0ec615cf20ee342f3bc29bc991b5ad66d8d2c\VC\Tools\MSVC\14.14.26428\atlmfc\include\atlhost.h(2810,9):  error: no matching function for call to 'AtlAxDialogCreateT'
return AtlAxDialogCreateT<LPCSTR, _AtlCreateDialogIndirectParamHelper, CreateDialogIndirectParamA>(hInstance, lpTemplateName, hWndParent, lpDialogProc, dwInitParam);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
..\..\third_party\depot_tools\win_toolchain\vs_files\3bc0ec615cf20ee342f3bc29bc991b5ad66d8d2c\VC\Tools\MSVC\14.14.26428\atlmfc\include\atlhost.h(2715,29):  note: candidate template ignored: invalid explicitly-specified argument for template parameter 'pFunc'
typename Helper::ReturnType AtlAxDialogCreateT(
^
4 errors generated.
rnk added a comment.Aug 13 2018, 6:56 PM

I went ahead and reverted this in rC339638, and will produce a reduction soon.

rnk added a comment.Aug 14 2018, 9:40 AM

The issue was related to ignored calling convention attributes on Win64:

int a(int, const int *, int, int, __int64);
class b {
public:
  typedef int c;
};
template <class d, class e,
          typename e::c(__stdcall f)(int, const int *, int, int, __int64)>
void AtlAxDialogCreateT(int, d, int, int, __int64);
int g, i, j, k;
char *h;
void l() { AtlAxDialogCreateT<char *, b, a>(g, h, i, j, k); }

Compiled with:
clang -c -fms-extensions -fms-compatibility --target=x86_64-windows-msvc