[clang] [llvm] [Clang] restrict use of attribute names reserved by the C++ standard (PR #106036)

Oleksandr T. via cfe-commits cfe-commits at lists.llvm.org
Tue Oct 22 12:19:49 PDT 2024


https://github.com/a-tarasyuk updated https://github.com/llvm/llvm-project/pull/106036

>From d4b07c7ff65ca64a5a434818ce09ecd289401340 Mon Sep 17 00:00:00 2001
From: Oleksandr T <oleksandr.tarasiuk at outlook.com>
Date: Tue, 10 Sep 2024 02:35:43 +0300
Subject: [PATCH] [Clang] restrict use of attribute names reserved by the C++
 standard

---
 clang/docs/ReleaseNotes.rst                   |  2 ++
 .../include/clang/Basic/AttributeCommonInfo.h |  2 +-
 clang/include/clang/Basic/CMakeLists.txt      |  5 +++
 clang/include/clang/Basic/DiagnosticGroups.td |  1 +
 .../include/clang/Basic/DiagnosticLexKinds.td |  2 ++
 clang/include/clang/Lex/Preprocessor.h        | 10 +++---
 clang/include/clang/Sema/CMakeLists.txt       |  5 ---
 clang/lib/Lex/PPDirectives.cpp                | 26 +++++++++++++-
 .../Preprocessor/macro-reserved-attrs1.cpp    | 34 +++++++++++++++++++
 .../Preprocessor/macro-reserved-attrs2.cpp    | 34 +++++++++++++++++++
 .../gn/secondary/clang/lib/Basic/BUILD.gn     |  5 +--
 .../gn/secondary/clang/lib/Sema/BUILD.gn      |  2 +-
 .../llvm-project-overlay/clang/BUILD.bazel    |  9 +++--
 13 files changed, 115 insertions(+), 22 deletions(-)
 create mode 100644 clang/test/Preprocessor/macro-reserved-attrs1.cpp
 create mode 100644 clang/test/Preprocessor/macro-reserved-attrs2.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 250821a9f9c45c..eecf5de3775f21 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -298,6 +298,8 @@ Improvements to Clang's diagnostics
 
 - Clang now warns for u8 character literals used in C23 with ``-Wpre-c23-compat`` instead of ``-Wpre-c++17-compat``.
 
+- Clang now diagnoses the use of attribute names reserved by the C++ standard. (#GH92196).
+
 Improvements to Clang's time-trace
 ----------------------------------
 
diff --git a/clang/include/clang/Basic/AttributeCommonInfo.h b/clang/include/clang/Basic/AttributeCommonInfo.h
index 5f024b4b5fd782..15e2685e049d9c 100644
--- a/clang/include/clang/Basic/AttributeCommonInfo.h
+++ b/clang/include/clang/Basic/AttributeCommonInfo.h
@@ -61,7 +61,7 @@ class AttributeCommonInfo {
   };
   enum Kind {
 #define PARSED_ATTR(NAME) AT_##NAME,
-#include "clang/Sema/AttrParsedAttrList.inc"
+#include "clang/Basic/AttrParsedAttrList.inc"
 #undef PARSED_ATTR
     NoSemaHandlerAttribute,
     IgnoredAttribute,
diff --git a/clang/include/clang/Basic/CMakeLists.txt b/clang/include/clang/Basic/CMakeLists.txt
index f069f4fc118f27..bcc34e86385926 100644
--- a/clang/include/clang/Basic/CMakeLists.txt
+++ b/clang/include/clang/Basic/CMakeLists.txt
@@ -31,6 +31,11 @@ clang_tablegen(AttrList.inc -gen-clang-attr-list
   SOURCE Attr.td
   TARGET ClangAttrList)
 
+clang_tablegen(AttrParsedAttrList.inc -gen-clang-attr-parsed-attr-list
+  -I ${CMAKE_CURRENT_SOURCE_DIR}/../../
+  SOURCE Attr.td
+  TARGET ClangAttrParsedAttrList)
+
 clang_tablegen(AttrSubMatchRulesList.inc -gen-clang-attr-subject-match-rule-list
   -I ${CMAKE_CURRENT_SOURCE_DIR}/../../
   SOURCE Attr.td
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index 116ce7a04f66f7..f04afce2da5a8c 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -751,6 +751,7 @@ def AmbiguousMacro : DiagGroup<"ambiguous-macro">;
 def KeywordAsMacro : DiagGroup<"keyword-macro">;
 def ReservedIdAsMacro : DiagGroup<"reserved-macro-identifier">;
 def ReservedIdAsMacroAlias : DiagGroup<"reserved-id-macro", [ReservedIdAsMacro]>;
+def ReservedAttributeIdentifier : DiagGroup<"reserved-attribute-identifier">;
 def RestrictExpansionMacro : DiagGroup<"restrict-expansion">;
 def FinalMacro : DiagGroup<"final-macro">;
 
diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td b/clang/include/clang/Basic/DiagnosticLexKinds.td
index fc14bb6aa21651..7e1964b6284c83 100644
--- a/clang/include/clang/Basic/DiagnosticLexKinds.td
+++ b/clang/include/clang/Basic/DiagnosticLexKinds.td
@@ -407,6 +407,8 @@ def warn_pp_macro_hides_keyword : Extension<
 def warn_pp_macro_is_reserved_id : Warning<
   "macro name is a reserved identifier">, DefaultIgnore,
   InGroup<ReservedIdAsMacro>;
+def warn_pp_macro_is_reserved_attribute_id : Warning<
+  "%0 is a reserved attribute identifier">, InGroup<ReservedAttributeIdentifier>;
 def warn_pp_objc_macro_redef_ignored : Warning<
   "ignoring redefinition of Objective-C qualifier macro">,
   InGroup<DiagGroup<"objc-macro-redefinition">>;
diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h
index 1307659e27d137..1e1d5ce0de48dc 100644
--- a/clang/include/clang/Lex/Preprocessor.h
+++ b/clang/include/clang/Lex/Preprocessor.h
@@ -2286,6 +2286,11 @@ class Preprocessor {
     }
   }
 
+  /// Determine whether the next preprocessor token to be
+  /// lexed is a '('.  If so, consume the token and return true, if not, this
+  /// method should have no observable side-effect on the lexed tokens.
+  bool isNextPPTokenLParen();
+
 private:
   /// Identifiers used for SEH handling in Borland. These are only
   /// allowed in particular circumstances
@@ -2650,11 +2655,6 @@ class Preprocessor {
 
   void removeCachedMacroExpandedTokensOfLastLexer();
 
-  /// Determine whether the next preprocessor token to be
-  /// lexed is a '('.  If so, consume the token and return true, if not, this
-  /// method should have no observable side-effect on the lexed tokens.
-  bool isNextPPTokenLParen();
-
   /// After reading "MACRO(", this method is invoked to read all of the formal
   /// arguments specified for the macro invocation.  Returns null on error.
   MacroArgs *ReadMacroCallArgumentList(Token &MacroName, MacroInfo *MI,
diff --git a/clang/include/clang/Sema/CMakeLists.txt b/clang/include/clang/Sema/CMakeLists.txt
index 0b0e31ece3195d..9077e22c2307cd 100644
--- a/clang/include/clang/Sema/CMakeLists.txt
+++ b/clang/include/clang/Sema/CMakeLists.txt
@@ -3,11 +3,6 @@ clang_tablegen(AttrTemplateInstantiate.inc -gen-clang-attr-template-instantiate
   SOURCE ../Basic/Attr.td
   TARGET ClangAttrTemplateInstantiate)
 
-clang_tablegen(AttrParsedAttrList.inc -gen-clang-attr-parsed-attr-list
-  -I ${CMAKE_CURRENT_SOURCE_DIR}/../../
-  SOURCE ../Basic/Attr.td
-  TARGET ClangAttrParsedAttrList)
-
 clang_tablegen(AttrParsedAttrKinds.inc -gen-clang-attr-parsed-attr-kinds
   -I ${CMAKE_CURRENT_SOURCE_DIR}/../../
   SOURCE ../Basic/Attr.td
diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp
index 4e77df9ec444c7..3cbba8d3a34d70 100644
--- a/clang/lib/Lex/PPDirectives.cpp
+++ b/clang/lib/Lex/PPDirectives.cpp
@@ -11,6 +11,8 @@
 ///
 //===----------------------------------------------------------------------===//
 
+#include "clang/Basic/AttributeCommonInfo.h"
+#include "clang/Basic/Attributes.h"
 #include "clang/Basic/CharInfo.h"
 #include "clang/Basic/DirectoryEntry.h"
 #include "clang/Basic/FileManager.h"
@@ -101,7 +103,8 @@ SourceRange Preprocessor::DiscardUntilEndOfDirective(Token &Tmp) {
 enum MacroDiag {
   MD_NoWarn,        //> Not a reserved identifier
   MD_KeywordDef,    //> Macro hides keyword, enabled by default
-  MD_ReservedMacro  //> #define of #undef reserved id, disabled by default
+  MD_ReservedMacro, //> #define of #undef reserved id, disabled by default
+  MD_ReservedAttributeIdentifier
 };
 
 /// Enumerates possible %select values for the pp_err_elif_after_else and
@@ -177,6 +180,20 @@ static bool isLanguageDefinedBuiltin(const SourceManager &SourceMgr,
   return false;
 }
 
+static bool isReservedCXXAttributeName(Preprocessor &PP, IdentifierInfo *II) {
+  const LangOptions &Lang = PP.getLangOpts();
+  if (Lang.CPlusPlus &&
+      hasAttribute(AttributeCommonInfo::Syntax::AS_CXX11, /*Scope*/ nullptr, II,
+                   PP.getTargetInfo(), Lang) > 0) {
+    AttributeCommonInfo::Kind AttrKind = AttributeCommonInfo::getParsedKind(
+        II, /*Scope*/ nullptr, AttributeCommonInfo::Syntax::AS_CXX11);
+    return !((AttrKind == AttributeCommonInfo::Kind::AT_Likely ||
+              AttrKind == AttributeCommonInfo::Kind::AT_Unlikely) &&
+             PP.isNextPPTokenLParen());
+  }
+  return false;
+}
+
 static MacroDiag shouldWarnOnMacroDef(Preprocessor &PP, IdentifierInfo *II) {
   const LangOptions &Lang = PP.getLangOpts();
   StringRef Text = II->getName();
@@ -186,6 +203,8 @@ static MacroDiag shouldWarnOnMacroDef(Preprocessor &PP, IdentifierInfo *II) {
     return MD_KeywordDef;
   if (Lang.CPlusPlus11 && (Text == "override" || Text == "final"))
     return MD_KeywordDef;
+  if (isReservedCXXAttributeName(PP, II))
+    return MD_ReservedAttributeIdentifier;
   return MD_NoWarn;
 }
 
@@ -194,6 +213,8 @@ static MacroDiag shouldWarnOnMacroUndef(Preprocessor &PP, IdentifierInfo *II) {
   // Do not warn on keyword undef.  It is generally harmless and widely used.
   if (isReservedInAllContexts(II->isReserved(Lang)))
     return MD_ReservedMacro;
+  if (isReservedCXXAttributeName(PP, II))
+    return MD_ReservedAttributeIdentifier;
   return MD_NoWarn;
 }
 
@@ -369,6 +390,9 @@ bool Preprocessor::CheckMacroName(Token &MacroNameTok, MacroUse isDefineUndef,
     }
     if (D == MD_ReservedMacro)
       Diag(MacroNameTok, diag::warn_pp_macro_is_reserved_id);
+    if (D == MD_ReservedAttributeIdentifier)
+      Diag(MacroNameTok, diag::warn_pp_macro_is_reserved_attribute_id)
+          << II->getName();
   }
 
   // Okay, we got a good identifier.
diff --git a/clang/test/Preprocessor/macro-reserved-attrs1.cpp b/clang/test/Preprocessor/macro-reserved-attrs1.cpp
new file mode 100644
index 00000000000000..6a7554e1b83a67
--- /dev/null
+++ b/clang/test/Preprocessor/macro-reserved-attrs1.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -pedantic %s
+
+#define noreturn 1 // expected-warning {{noreturn is a reserved attribute identifier}}
+#undef noreturn    // expected-warning {{noreturn is a reserved attribute identifier}}
+
+#define assume 1 // expected-warning {{assume is a reserved attribute identifier}}
+#undef assume    // expected-warning {{assume is a reserved attribute identifier}}
+
+#define carries_dependency 1 // expected-warning {{carries_dependency is a reserved attribute identifier}}
+#undef carries_dependency    // expected-warning {{carries_dependency is a reserved attribute identifier}}
+
+#define deprecated 1 // expected-warning {{deprecated is a reserved attribute identifier}}
+#undef deprecated    // expected-warning {{deprecated is a reserved attribute identifier}}
+
+#define fallthrough 1 // expected-warning {{fallthrough is a reserved attribute identifier}}
+#undef fallthrough    // expected-warning {{fallthrough is a reserved attribute identifier}}
+
+#define likely 1 // expected-warning {{likely is a reserved attribute identifier}}
+#undef likely    // expected-warning {{likely is a reserved attribute identifier}}
+
+#define no_unique_address 1 // expected-warning {{no_unique_address is a reserved attribute identifier}}
+#undef no_unique_address    // expected-warning {{no_unique_address is a reserved attribute identifier}}
+
+#define unlikely 1 // expected-warning {{unlikely is a reserved attribute identifier}}
+#undef unlikely    // expected-warning {{unlikely is a reserved attribute identifier}}
+
+#define maybe_unused 1 // expected-warning {{maybe_unused is a reserved attribute identifier}}
+#undef maybe_unused    // expected-warning {{maybe_unused is a reserved attribute identifier}}
+
+#define nodiscard 1 // expected-warning {{nodiscard is a reserved attribute identifier}}
+#undef nodiscard    // expected-warning {{nodiscard is a reserved attribute identifier}}
+
+#define likely() 1   // ok
+#define unlikely() 1 // ok
diff --git a/clang/test/Preprocessor/macro-reserved-attrs2.cpp b/clang/test/Preprocessor/macro-reserved-attrs2.cpp
new file mode 100644
index 00000000000000..eddbe0cebb74ab
--- /dev/null
+++ b/clang/test/Preprocessor/macro-reserved-attrs2.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -pedantic %s
+
+#define noreturn // expected-warning {{noreturn is a reserved attribute identifier}}
+#undef noreturn  // expected-warning {{noreturn is a reserved attribute identifier}}
+
+#define assume // expected-warning {{assume is a reserved attribute identifier}}
+#undef assume  // expected-warning {{assume is a reserved attribute identifier}}
+
+#define carries_dependency // expected-warning {{carries_dependency is a reserved attribute identifier}}
+#undef carries_dependency  // expected-warning {{carries_dependency is a reserved attribute identifier}}
+
+#define deprecated // expected-warning {{deprecated is a reserved attribute identifier}}
+#undef deprecated  // expected-warning {{deprecated is a reserved attribute identifier}}
+
+#define fallthrough // expected-warning {{fallthrough is a reserved attribute identifier}}
+#undef fallthrough  // expected-warning {{fallthrough is a reserved attribute identifier}}
+
+#define likely // expected-warning {{likely is a reserved attribute identifier}}
+#undef likely  // expected-warning {{likely is a reserved attribute identifier}}
+
+#define no_unique_address // expected-warning {{no_unique_address is a reserved attribute identifier}}
+#undef no_unique_address  // expected-warning {{no_unique_address is a reserved attribute identifier}}
+
+#define unlikely // expected-warning {{unlikely is a reserved attribute identifier}}
+#undef unlikely  // expected-warning {{unlikely is a reserved attribute identifier}}
+
+#define maybe_unused // expected-warning {{maybe_unused is a reserved attribute identifier}}
+#undef maybe_unused  // expected-warning {{maybe_unused is a reserved attribute identifier}}
+
+#define nodiscard // expected-warning {{nodiscard is a reserved attribute identifier}}
+#undef nodiscard  // expected-warning {{nodiscard is a reserved attribute identifier}}
+
+#define likely()   // ok
+#define unlikely() // ok
diff --git a/llvm/utils/gn/secondary/clang/lib/Basic/BUILD.gn b/llvm/utils/gn/secondary/clang/lib/Basic/BUILD.gn
index 84d569d3426544..b8360ff81c9d10 100644
--- a/llvm/utils/gn/secondary/clang/lib/Basic/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang/lib/Basic/BUILD.gn
@@ -22,6 +22,7 @@ static_library("Basic") {
   public_deps = [
     # public_dep because public header Version.h includes generated Version.inc.
     "//clang/include/clang/Basic:AttrList",
+    "//clang/include/clang/Basic:AttrParsedAttrList",
     "//clang/include/clang/Basic:AttrSubMatchRulesList",
     "//clang/include/clang/Basic:Builtins",
     "//clang/include/clang/Basic:BuiltinsBPF",
@@ -39,10 +40,6 @@ static_library("Basic") {
     "//clang/include/clang/Basic:riscv_vector_builtins",
     "//clang/include/clang/Basic:version",
 
-    # public_dep because public header AttributeCommonInfo.h includes generated
-    # AttrParsedAttrList.inc.
-    "//clang/include/clang/Sema:AttrParsedAttrList",
-
     # public_dep because public header OpenMPKinds.h includes generated
     # OMP.h.inc.
     "//llvm/include/llvm/Frontend/OpenMP:public_tablegen",
diff --git a/llvm/utils/gn/secondary/clang/lib/Sema/BUILD.gn b/llvm/utils/gn/secondary/clang/lib/Sema/BUILD.gn
index 83a10d5b18bc83..2aa70151c49266 100644
--- a/llvm/utils/gn/secondary/clang/lib/Sema/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang/lib/Sema/BUILD.gn
@@ -9,6 +9,7 @@ static_library("Sema") {
   configs += [ "//llvm/utils/gn/build:clang_code" ]
   deps = [
     ":OpenCLBuiltins",
+    "//clang/include/clang/Basic:AttrParsedAttrList",
     "//clang/include/clang/Basic:arm_cde_builtin_aliases",
     "//clang/include/clang/Basic:arm_cde_builtin_sema",
     "//clang/include/clang/Basic:arm_mve_builtin_aliases",
@@ -22,7 +23,6 @@ static_library("Sema") {
     "//clang/include/clang/Basic:riscv_vector_builtin_sema",
     "//clang/include/clang/Sema:AttrParsedAttrImpl",
     "//clang/include/clang/Sema:AttrParsedAttrKinds",
-    "//clang/include/clang/Sema:AttrParsedAttrList",
     "//clang/include/clang/Sema:AttrSpellingListIndex",
     "//clang/include/clang/Sema:AttrTemplateInstantiate",
     "//clang/lib/APINotes",
diff --git a/utils/bazel/llvm-project-overlay/clang/BUILD.bazel b/utils/bazel/llvm-project-overlay/clang/BUILD.bazel
index 1d0ba8bd4d586d..7885d0b47a2ef8 100644
--- a/utils/bazel/llvm-project-overlay/clang/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/clang/BUILD.bazel
@@ -529,6 +529,10 @@ gentbl(
             "-gen-clang-attr-list",
             "include/clang/Basic/AttrList.inc",
         ),
+        (
+            "-gen-clang-attr-parsed-attr-list",
+            "include/clang/Basic/AttrParsedAttrList.inc",
+        ),
         (
             "-gen-clang-attr-subject-match-rule-list",
             "include/clang/Basic/AttrSubMatchRulesList.inc",
@@ -1096,10 +1100,6 @@ gentbl(
             "-gen-clang-attr-parsed-attr-kinds",
             "include/clang/Sema/AttrParsedAttrKinds.inc",
         ),
-        (
-            "-gen-clang-attr-parsed-attr-list",
-            "include/clang/Sema/AttrParsedAttrList.inc",
-        ),
         (
             "-gen-clang-attr-spelling-index",
             "include/clang/Sema/AttrSpellingListIndex.inc",
@@ -1135,7 +1135,6 @@ cc_library(
     textual_hdrs = [
         "include/clang/Sema/AttrParsedAttrImpl.inc",
         "include/clang/Sema/AttrParsedAttrKinds.inc",
-        "include/clang/Sema/AttrParsedAttrList.inc",
         "include/clang/Sema/AttrSpellingListIndex.inc",
         "include/clang/Sema/AttrTemplateInstantiate.inc",
         "lib/Sema/OpenCLBuiltins.inc",



More information about the cfe-commits mailing list