ldionne updated this revision to Diff 347069.
ldionne marked an inline comment as done.
ldionne added a comment.
Herald added a project: clang.
Rebase onto main and apply Aaron's comment.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D91630/new/
https://reviews.llvm.org/D91630
Files:
clang/docs/LanguageExtensions.rst
clang/docs/ReleaseNotes.rst
clang/include/clang/Basic/DiagnosticParseKinds.td
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/include/clang/Basic/Features.def
clang/include/clang/Parse/Parser.h
clang/lib/Parse/ParseDecl.cpp
clang/lib/Parse/ParseDeclCXX.cpp
clang/lib/Sema/SemaDeclAttr.cpp
clang/lib/Sema/SemaDeclCXX.cpp
clang/test/Parser/cxx0x-attributes.cpp
clang/test/SemaCXX/cxx11-attributes-on-using-declaration.cpp
Index: clang/test/SemaCXX/cxx11-attributes-on-using-declaration.cpp
===================================================================
--- /dev/null
+++ clang/test/SemaCXX/cxx11-attributes-on-using-declaration.cpp
@@ -0,0 +1,42 @@
+// RUN: %clang_cc1 -pedantic -triple x86_64-apple-macos11 -std=c++20 -fsyntax-only -verify %s
+
+static_assert(__has_extension(cxx_attributes_on_using_declarations), "");
+
+namespace NS { typedef int x; }
+
+[[clang::annotate("foo")]] using NS::x; // expected-warning{{ISO C++ does not allow an attribute list to appear here}}
+
+
+[[deprecated]] using NS::x; // expected-warning {{'deprecated' currently has no effect on using-declarations}} expected-warning{{ISO C++ does not allow}}
+using NS::x [[deprecated]]; // expected-warning {{'deprecated' currently has no effect on using-declarations}} expected-warning{{ISO C++ does not allow}}
+using NS::x __attribute__((deprecated)); // expected-warning {{'deprecated' currently has no effect on using-declarations}}
+using NS::x __attribute__((availability(macos,introduced=1))); // expected-warning {{'availability' currently has no effect on using-declarations}}
+
+[[clang::availability(macos,introduced=1)]] using NS::x; // expected-warning {{'availability' currently has no effect on using-declarations}} expected-warning{{ISO C++ does not allow}}
+
+// expected-warning@+1 3 {{ISO C++ does not allow an attribute list to appear here}}
+[[clang::annotate("A")]] using NS::x [[clang::annotate("Y")]], NS::x [[clang::annotate("Z")]];
+
+template <class T>
+struct S : T {
+ [[deprecated]] using typename T::x; // expected-warning{{ISO C++ does not allow}} expected-warning {{'deprecated' currently has no effect on using-declarations}}
+ [[deprecated]] using T::y; // expected-warning{{ISO C++ does not allow}} expected-warning {{'deprecated' currently has no effect on using-declarations}}
+
+ using typename T::z [[deprecated]]; // expected-warning{{ISO C++ does not allow}} expected-warning {{'deprecated' currently has no effect on using-declarations}}
+ using T::a [[deprecated]]; // expected-warning{{ISO C++ does not allow}} expected-warning {{'deprecated' currently has no effect on using-declarations}}
+};
+
+struct Base {};
+
+template <class B>
+struct DepBase1 : B {
+ using B::B [[]];
+
+};
+template <class B>
+struct DepBase2 : B {
+ using B::B __attribute__(());
+};
+
+DepBase1<Base> db1;
+DepBase2<Base> db2;
Index: clang/test/Parser/cxx0x-attributes.cpp
===================================================================
--- clang/test/Parser/cxx0x-attributes.cpp
+++ clang/test/Parser/cxx0x-attributes.cpp
@@ -131,12 +131,12 @@
[[]] static_assert(true, ""); //expected-error {{an attribute list cannot appear here}}
[[]] asm(""); // expected-error {{an attribute list cannot appear here}}
-[[]] using ns::i; // expected-error {{an attribute list cannot appear here}}
+[[]] using ns::i;
[[unknown]] using namespace ns; // expected-warning {{unknown attribute 'unknown' ignored}}
[[noreturn]] using namespace ns; // expected-error {{'noreturn' attribute only applies to functions}}
namespace [[]] ns2 {} // expected-warning {{attributes on a namespace declaration are a C++17 extension}}
-using [[]] alignas(4) [[]] ns::i; // expected-error {{an attribute list cannot appear here}}
+using [[]] alignas(4) [[]] ns::i; // expected-error {{an attribute list cannot appear here}} expected-error {{'alignas' attribute only applies to variables, data members and tag types}} expected-warning {{ISO C++}}
using [[]] alignas(4) [[]] foobar = int; // expected-error {{an attribute list cannot appear here}} expected-error {{'alignas' attribute only applies to}}
void bad_attributes_in_do_while() {
@@ -157,7 +157,16 @@
[[]] using T = int; // expected-error {{an attribute list cannot appear here}}
using T [[]] = int; // ok
template<typename T> using U [[]] = T;
-using ns::i [[]]; // expected-error {{an attribute list cannot appear here}}
+using ns::i [[]];
+using ns::i [[]], ns::i [[]]; // expected-warning {{use of multiple declarators in a single using declaration is a C++17 extension}}
+struct using_in_struct_base {
+ typedef int i, j, k, l;
+};
+struct using_in_struct : using_in_struct_base {
+ [[]] using using_in_struct_base::i;
+ using using_in_struct_base::j [[]];
+ [[]] using using_in_struct_base::k [[]], using_in_struct_base::l [[]]; // expected-warning {{use of multiple declarators in a single using declaration is a C++17 extension}}
+};
using [[]] ns::i; // expected-error {{an attribute list cannot appear here}}
using T [[unknown]] = int; // expected-warning {{unknown attribute 'unknown' ignored}}
using T [[noreturn]] = int; // expected-error {{'noreturn' attribute only applies to functions}}
Index: clang/lib/Sema/SemaDeclCXX.cpp
===================================================================
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -12071,9 +12071,9 @@
return nullptr;
DeclContext *LookupContext = computeDeclContext(SS);
- NamedDecl *D;
NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context);
if (!LookupContext || EllipsisLoc.isValid()) {
+ NamedDecl *D;
if (HasTypenameKeyword) {
// FIXME: not all declaration name kinds are legal here
D = UnresolvedUsingTypenameDecl::Create(Context, CurContext,
@@ -12087,6 +12087,7 @@
}
D->setAccess(AS);
CurContext->addDecl(D);
+ ProcessDeclAttributeList(S, D, AttrList);
return D;
}
@@ -12096,6 +12097,7 @@
UsingName, HasTypenameKeyword);
UD->setAccess(AS);
CurContext->addDecl(UD);
+ ProcessDeclAttributeList(S, UD, AttrList);
UD->setInvalidDecl(Invalid);
return UD;
};
Index: clang/lib/Sema/SemaDeclAttr.cpp
===================================================================
--- clang/lib/Sema/SemaDeclAttr.cpp
+++ clang/lib/Sema/SemaDeclAttr.cpp
@@ -2446,6 +2446,13 @@
}
static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (isa<UsingDecl, UnresolvedUsingTypenameDecl,
+ UnresolvedUsingValueDecl>(D)) {
+ S.Diag(AL.getRange().getBegin(), diag::warn_deprecated_ignored_on_using)
+ << AL;
+ return;
+ }
+
if (!AL.checkExactlyNumArgs(S, 1))
return;
IdentifierLoc *Platform = AL.getArgAsIdent(0);
@@ -7249,6 +7256,11 @@
// namespace.
return;
}
+ } else if (isa<UsingDecl, UnresolvedUsingTypenameDecl,
+ UnresolvedUsingValueDecl>(D)) {
+ S.Diag(AL.getRange().getBegin(), diag::warn_deprecated_ignored_on_using)
+ << AL;
+ return;
}
// Handle the cases where the attribute has a text message.
Index: clang/lib/Parse/ParseDeclCXX.cpp
===================================================================
--- clang/lib/Parse/ParseDeclCXX.cpp
+++ clang/lib/Parse/ParseDeclCXX.cpp
@@ -497,12 +497,8 @@
}
// Otherwise, it must be a using-declaration or an alias-declaration.
-
- // Using declarations can't have attributes.
- ProhibitAttributes(attrs);
-
return ParseUsingDeclaration(Context, TemplateInfo, UsingLoc, DeclEnd,
- AS_none);
+ attrs, AS_none);
}
/// ParseUsingDirective - Parse C++ using-directive, assumes
@@ -627,7 +623,8 @@
if (getLangOpts().CPlusPlus11 && Context == DeclaratorContext::Member &&
Tok.is(tok::identifier) &&
(NextToken().is(tok::semi) || NextToken().is(tok::comma) ||
- NextToken().is(tok::ellipsis)) &&
+ NextToken().is(tok::ellipsis) || NextToken().is(tok::l_square) ||
+ NextToken().is(tok::kw___attribute)) &&
D.SS.isNotEmpty() && LastII == Tok.getIdentifierInfo() &&
!D.SS.getScopeRep()->getAsNamespace() &&
!D.SS.getScopeRep()->getAsNamespaceAlias()) {
@@ -674,6 +671,7 @@
Parser::ParseUsingDeclaration(DeclaratorContext Context,
const ParsedTemplateInfo &TemplateInfo,
SourceLocation UsingLoc, SourceLocation &DeclEnd,
+ ParsedAttributesWithRange &PrefixAttrs,
AccessSpecifier AS) {
// Check for misplaced attributes before the identifier in an
// alias-declaration.
@@ -686,6 +684,17 @@
ParsedAttributesWithRange Attrs(AttrFactory);
MaybeParseAttributes(PAKM_GNU | PAKM_CXX11, Attrs);
+ // If we had any misplaced attributes from earlier, this is where they
+ // should have been written.
+ if (MisplacedAttrs.Range.isValid()) {
+ Diag(MisplacedAttrs.Range.getBegin(), diag::err_attributes_not_allowed)
+ << FixItHint::CreateInsertionFromRange(
+ Tok.getLocation(),
+ CharSourceRange::getTokenRange(MisplacedAttrs.Range))
+ << FixItHint::CreateRemoval(MisplacedAttrs.Range);
+ Attrs.takeAllFrom(MisplacedAttrs);
+ }
+
// Maybe this is an alias-declaration.
if (Tok.is(tok::equal)) {
if (InvalidDeclarator) {
@@ -693,16 +702,7 @@
return nullptr;
}
- // If we had any misplaced attributes from earlier, this is where they
- // should have been written.
- if (MisplacedAttrs.Range.isValid()) {
- Diag(MisplacedAttrs.Range.getBegin(), diag::err_attributes_not_allowed)
- << FixItHint::CreateInsertionFromRange(
- Tok.getLocation(),
- CharSourceRange::getTokenRange(MisplacedAttrs.Range))
- << FixItHint::CreateRemoval(MisplacedAttrs.Range);
- Attrs.takeAllFrom(MisplacedAttrs);
- }
+ ProhibitAttributes(PrefixAttrs);
Decl *DeclFromDeclSpec = nullptr;
Decl *AD = ParseAliasDeclarationAfterDeclarator(
@@ -710,10 +710,7 @@
return Actions.ConvertDeclToDeclGroup(AD, DeclFromDeclSpec);
}
- // C++11 attributes are not allowed on a using-declaration, but GNU ones
- // are.
- ProhibitAttributes(MisplacedAttrs);
- ProhibitAttributes(Attrs);
+ DiagnoseCXX11AttributeExtension(PrefixAttrs);
// Diagnose an attempt to declare a templated using-declaration.
// In C++11, alias-declarations can be templates:
@@ -731,8 +728,10 @@
SmallVector<Decl *, 8> DeclsInGroup;
while (true) {
- // Parse (optional) attributes (most likely GNU strong-using extension).
- MaybeParseGNUAttributes(Attrs);
+ // Parse (optional) attributes.
+ MaybeParseAttributes(PAKM_GNU | PAKM_CXX11, Attrs);
+ DiagnoseCXX11AttributeExtension(Attrs);
+ Attrs.addAll(PrefixAttrs.begin(), PrefixAttrs.end());
if (InvalidDeclarator)
SkipUntil(tok::comma, tok::semi, StopBeforeMatch);
@@ -2618,8 +2617,6 @@
MaybeParseMicrosoftAttributes(attrs);
if (Tok.is(tok::kw_using)) {
- ProhibitAttributes(attrs);
-
// Eat 'using'.
SourceLocation UsingLoc = ConsumeToken();
@@ -2638,7 +2635,7 @@
SourceLocation DeclEnd;
// Otherwise, it must be a using-declaration or an alias-declaration.
return ParseUsingDeclaration(DeclaratorContext::Member, TemplateInfo,
- UsingLoc, DeclEnd, AS);
+ UsingLoc, DeclEnd, attrs, AS);
}
// Hold late-parsed attributes so we can attach a Decl to them later.
Index: clang/lib/Parse/ParseDecl.cpp
===================================================================
--- clang/lib/Parse/ParseDecl.cpp
+++ clang/lib/Parse/ParseDecl.cpp
@@ -1650,6 +1650,13 @@
}
}
+void Parser::DiagnoseCXX11AttributeExtension(ParsedAttributesWithRange &Attrs) {
+ for (const ParsedAttr &PA : Attrs) {
+ if (PA.isCXX11Attribute() || PA.isC2xAttribute())
+ Diag(PA.getLoc(), diag::ext_cxx11_attr_placement) << PA << PA.getRange();
+ }
+}
+
// Usually, `__attribute__((attrib)) class Foo {} var` means that attribute
// applies to var, not the type Foo.
// As an exception to the rule, __declspec(align(...)) before the
Index: clang/include/clang/Parse/Parser.h
===================================================================
--- clang/include/clang/Parse/Parser.h
+++ clang/include/clang/Parse/Parser.h
@@ -2633,6 +2633,10 @@
/// locations where attributes are not allowed.
void DiagnoseAndSkipCXX11Attributes();
+ /// Emit warnings for C++11 and C2x attributes that are in a position that
+ /// clang accepts as an extension.
+ void DiagnoseCXX11AttributeExtension(ParsedAttributesWithRange &Attrs);
+
/// Parses syntax-generic attribute arguments for attributes which are
/// known to the implementation, and adds them to the given ParsedAttributes
/// list with the given attribute syntax. Returns the number of arguments
@@ -3058,6 +3062,7 @@
const ParsedTemplateInfo &TemplateInfo,
SourceLocation UsingLoc,
SourceLocation &DeclEnd,
+ ParsedAttributesWithRange &Attrs,
AccessSpecifier AS = AS_none);
Decl *ParseAliasDeclarationAfterDeclarator(
const ParsedTemplateInfo &TemplateInfo, SourceLocation UsingLoc,
Index: clang/include/clang/Basic/Features.def
===================================================================
--- clang/include/clang/Basic/Features.def
+++ clang/include/clang/Basic/Features.def
@@ -258,6 +258,7 @@
EXTENSION(gnu_asm_goto_with_outputs, LangOpts.GNUAsm)
EXTENSION(matrix_types, LangOpts.MatrixTypes)
EXTENSION(matrix_types_scalar_division, true)
+EXTENSION(cxx_attributes_on_using_declarations, LangOpts.CPlusPlus11)
FEATURE(cxx_abi_relative_vtable, LangOpts.CPlusPlus && LangOpts.RelativeCXXABIVTables)
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3957,6 +3957,9 @@
def warn_attribute_sentinel_not_variadic : Warning<
"'sentinel' attribute only supported for variadic %select{functions|blocks}0">,
InGroup<IgnoredAttributes>;
+def warn_deprecated_ignored_on_using : Warning<
+ "%0 currently has no effect on using-declarations">,
+ InGroup<IgnoredAttributes>;
def err_attribute_sentinel_less_than_zero : Error<
"'sentinel' parameter 1 less than zero">;
def err_attribute_sentinel_not_zero_or_one : Error<
Index: clang/include/clang/Basic/DiagnosticParseKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticParseKinds.td
+++ clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -693,6 +693,9 @@
def err_using_attribute_ns_conflict : Error<
"attribute with scope specifier cannot follow default scope specifier">;
def err_attributes_not_allowed : Error<"an attribute list cannot appear here">;
+def ext_cxx11_attr_placement : ExtWarn<
+ "ISO C++ does not allow an attribute list to appear here">,
+ InGroup<DiagGroup<"cxx-attribute-extension">>;
def err_attributes_misplaced : Error<"misplaced attributes; expected attributes here">;
def err_l_square_l_square_not_attribute : Error<
"C++11 only allows consecutive left square brackets when "
Index: clang/docs/ReleaseNotes.rst
===================================================================
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -111,6 +111,9 @@
- ...
+- Added support for C++11-style ``[[]]`` attributes on using-declarations, as a
+ clang extension.
+
Windows Support
---------------
Index: clang/docs/LanguageExtensions.rst
===================================================================
--- clang/docs/LanguageExtensions.rst
+++ clang/docs/LanguageExtensions.rst
@@ -632,6 +632,20 @@
Query for this feature with ``__has_extension(enumerator_attributes)``.
+C++11 Attributes on using-declarations
+======================================
+
+Clang allows C++-style ``[[]]`` attributes to be written on using-declarations.
+For instance:
+
+.. code-block:: c++
+
+ [[clang::using_if_exists]] using foo::bar;
+ using foo::baz [[clang::using_if_exists]];
+
+You can test for support for this extension with
+``__has_extension(cxx_attributes_on_using_declarations)``.
+
'User-Specified' System Frameworks
==================================
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits