[clang] [Clang] Add __ugly__ spelling for the msvc attribute scope (PR #113765)

Nikolas Klauser via cfe-commits cfe-commits at lists.llvm.org
Sat Oct 26 09:00:02 PDT 2024


https://github.com/philnik777 created https://github.com/llvm/llvm-project/pull/113765

This is required to avoid macro clashing when using attributes like `[[msvc::no_unique_address]]`.

This patch also refactor the logic for attribute scope __uglification__ into a single place to make it easier to add additional cases in case another one is required at some point again.



>From 68f3617027fa09b531b5e3eaea6a025c6783a258 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Sat, 26 Oct 2024 17:57:09 +0200
Subject: [PATCH] [Clang] Add __ugly__ spelling for the msvc attribute scope

---
 clang/include/clang/Basic/Attributes.h        | 24 +++++++++++++++++++
 clang/lib/Basic/Attributes.cpp                | 23 +++++++-----------
 clang/lib/Sema/SemaCodeComplete.cpp           | 23 ++++--------------
 .../SemaCXX/cxx2a-ms-no-unique-address.cpp    |  3 +++
 4 files changed, 40 insertions(+), 33 deletions(-)

diff --git a/clang/include/clang/Basic/Attributes.h b/clang/include/clang/Basic/Attributes.h
index 61666a6f4d9ac4..9fa7e5ce55d491 100644
--- a/clang/include/clang/Basic/Attributes.h
+++ b/clang/include/clang/Basic/Attributes.h
@@ -23,6 +23,30 @@ int hasAttribute(AttributeCommonInfo::Syntax Syntax,
                  const IdentifierInfo *Scope, const IdentifierInfo *Attr,
                  const TargetInfo &Target, const LangOptions &LangOpts);
 
+inline const char* deuglifyAttrScope(StringRef Scope) {
+  if (Scope == "_Clang")
+    return "clang";
+  if (Scope == "__gnu__")
+    return "gnu";
+  if (Scope == "__msvc__")
+    return "msvc";
+  return nullptr;
+}
+
+inline const char* uglifyAttrScope(StringRef Scope) {
+  if (Scope == "clang")
+    return "_Clang";
+  if (Scope == "gnu")
+    return "__gnu__";
+  if (Scope == "msvc")
+    return "__msvc__";
+  return nullptr;
+}
+
+inline bool isPotentiallyUglyScope(StringRef Scope) {
+  return Scope == "gnu" || Scope == "clang" || Scope == "msvc";
+}
+
 } // end namespace clang
 
 #endif // LLVM_CLANG_BASIC_ATTRIBUTES_H
diff --git a/clang/lib/Basic/Attributes.cpp b/clang/lib/Basic/Attributes.cpp
index 867d241a2cf847..4afa129e3b2222 100644
--- a/clang/lib/Basic/Attributes.cpp
+++ b/clang/lib/Basic/Attributes.cpp
@@ -38,10 +38,8 @@ int clang::hasAttribute(AttributeCommonInfo::Syntax Syntax,
 
   // Normalize the scope name, but only for gnu and clang attributes.
   StringRef ScopeName = Scope ? Scope->getName() : "";
-  if (ScopeName == "__gnu__")
-    ScopeName = "gnu";
-  else if (ScopeName == "_Clang")
-    ScopeName = "clang";
+  if (const char *prettyName = deuglifyAttrScope(ScopeName))
+    ScopeName = prettyName;
 
   // As a special case, look for the omp::sequence and omp::directive
   // attributes. We support those, but not through the typical attribute
@@ -87,10 +85,8 @@ normalizeAttrScopeName(const IdentifierInfo *Scope,
   StringRef ScopeName = Scope->getName();
   if (SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||
       SyntaxUsed == AttributeCommonInfo::AS_C23) {
-    if (ScopeName == "__gnu__")
-      ScopeName = "gnu";
-    else if (ScopeName == "_Clang")
-      ScopeName = "clang";
+    if (const char *prettySpelling = deuglifyAttrScope(ScopeName))
+      return prettySpelling;
   }
   return ScopeName;
 }
@@ -100,12 +96,11 @@ static StringRef normalizeAttrName(const IdentifierInfo *Name,
                                    AttributeCommonInfo::Syntax SyntaxUsed) {
   // Normalize the attribute name, __foo__ becomes foo. This is only allowable
   // for GNU attributes, and attributes using the double square bracket syntax.
-  bool ShouldNormalize =
-      SyntaxUsed == AttributeCommonInfo::AS_GNU ||
-      ((SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||
-        SyntaxUsed == AttributeCommonInfo::AS_C23) &&
-       (NormalizedScopeName.empty() || NormalizedScopeName == "gnu" ||
-        NormalizedScopeName == "clang"));
+  bool ShouldNormalize = SyntaxUsed == AttributeCommonInfo::AS_GNU ||
+                         ((SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||
+                           SyntaxUsed == AttributeCommonInfo::AS_C23) &&
+                          (NormalizedScopeName.empty() ||
+                           isPotentiallyUglyScope(NormalizedScopeName)));
   StringRef AttrName = Name->getName();
   if (ShouldNormalize && AttrName.size() >= 4 && AttrName.starts_with("__") &&
       AttrName.ends_with("__"))
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index 3e31f3d82657a3..732da9ceb0628f 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -25,6 +25,7 @@
 #include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/Type.h"
 #include "clang/Basic/AttributeCommonInfo.h"
+#include "clang/Basic/Attributes.h"
 #include "clang/Basic/CharInfo.h"
 #include "clang/Basic/OperatorKinds.h"
 #include "clang/Basic/Specifiers.h"
@@ -4579,22 +4580,6 @@ void SemaCodeCompletion::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
                             Results.size());
 }
 
-static const char *underscoreAttrScope(llvm::StringRef Scope) {
-  if (Scope == "clang")
-    return "_Clang";
-  if (Scope == "gnu")
-    return "__gnu__";
-  return nullptr;
-}
-
-static const char *noUnderscoreAttrScope(llvm::StringRef Scope) {
-  if (Scope == "_Clang")
-    return "clang";
-  if (Scope == "__gnu__")
-    return "gnu";
-  return nullptr;
-}
-
 void SemaCodeCompletion::CodeCompleteAttribute(
     AttributeCommonInfo::Syntax Syntax, AttributeCompletion Completion,
     const IdentifierInfo *InScope) {
@@ -4618,7 +4603,7 @@ void SemaCodeCompletion::CodeCompleteAttribute(
   bool InScopeUnderscore = false;
   if (InScope) {
     InScopeName = InScope->getName();
-    if (const char *NoUnderscore = noUnderscoreAttrScope(InScopeName)) {
+    if (const char *NoUnderscore = deuglifyAttrScope(InScopeName)) {
       InScopeName = NoUnderscore;
       InScopeUnderscore = true;
     }
@@ -4653,7 +4638,7 @@ void SemaCodeCompletion::CodeCompleteAttribute(
           Results.AddResult(
               CodeCompletionResult(Results.getAllocator().CopyString(Scope)));
           // Include alternate form (__gnu__ instead of gnu).
-          if (const char *Scope2 = underscoreAttrScope(Scope))
+          if (const char *Scope2 = uglifyAttrScope(Scope))
             Results.AddResult(CodeCompletionResult(Scope2));
         }
         continue;
@@ -4712,7 +4697,7 @@ void SemaCodeCompletion::CodeCompleteAttribute(
         if (Scope.empty()) {
           Add(Scope, Name, /*Underscores=*/true);
         } else {
-          const char *GuardedScope = underscoreAttrScope(Scope);
+          const char *GuardedScope = uglifyAttrScope(Scope);
           if (!GuardedScope)
             continue;
           Add(GuardedScope, Name, /*Underscores=*/true);
diff --git a/clang/test/SemaCXX/cxx2a-ms-no-unique-address.cpp b/clang/test/SemaCXX/cxx2a-ms-no-unique-address.cpp
index 822ed752fa9c75..c9cf86f5270034 100644
--- a/clang/test/SemaCXX/cxx2a-ms-no-unique-address.cpp
+++ b/clang/test/SemaCXX/cxx2a-ms-no-unique-address.cpp
@@ -16,6 +16,9 @@ struct [[msvc::no_unique_address]] S { // expected-error {{only applies to non-b
   [[msvc::no_unique_address()]] int arglist; // expected-error {{cannot have an argument list}} unsupported-warning {{unknown}}
 
   int [[msvc::no_unique_address]] c; // expected-error {{cannot be applied to types}} unsupported-error {{cannot be applied to types}}
+  [[__msvc__::__no_unique_address__]] int d; // unsupported-warning {{unknown}}
+  [[__msvc__::no_unique_address]] int e; // unsupported-warning {{unknown}}
+  [[msvc::__no_unique_address__]] int g; // unsupported-warning {{unknown}}
 };
 
 struct CStructNoUniqueAddress {



More information about the cfe-commits mailing list