[clang] [clang] Fix compile-time regression from attribute arg checking change (PR #101768)
Mike Rice via cfe-commits
cfe-commits at lists.llvm.org
Fri Aug 2 15:57:37 PDT 2024
https://github.com/mikerice1969 created https://github.com/llvm/llvm-project/pull/101768
In 2acf77f987331c05520c5bfd849326909ffce983 code was added to use the 'full' name including syntax and scope.
Instead of building up a large string for each name, add syntax and scope checks to the value expression in tablegen.
There is already code to generate expressions for target specific attributes. This change refactors and adds to that code to include syntax and scope checks.
The tablegen avoids generating the complicated expression unless there are two attributes using the same name, otherwise the case values will be as simple as before.
Removes the currently unused attributeHasStrictIdentifierArgAtIndex function and the related tablegen.
>From 4cc7055227ea8115c93c806c42270d7da8e6e89d Mon Sep 17 00:00:00 2001
From: Mike Rice <michael.p.rice at intel.com>
Date: Fri, 2 Aug 2024 14:34:02 -0700
Subject: [PATCH 1/2] [clang] Fix compile-time regression from attribute arg
checking change
In 2acf77f987331c05520c5bfd849326909ffce983 code was added to use the
'full' name including syntax and scope.
Instead of building up a large string for each name, add syntax and
scope checks to the value expression in tablegen.
There is already code to generate expressions for target specific
attributes. This change refactors and adds to that code to include
syntax and scope checks.
The tablegen avoids generating the complicated expression unless there
are two attributes using the same name, otherwise the case values will
be as simple as before.
Removes the currently unused attributeHasStrictIdentifierArgAtIndex
function and the related tablegen.
---
.../include/clang/Basic/AttributeCommonInfo.h | 6 -
clang/lib/Basic/Attributes.cpp | 34 ---
clang/lib/Parse/ParseDecl.cpp | 71 ++---
.../TableGen/attrs-parser-string-switches.td | 132 ++++-----
clang/utils/TableGen/ClangAttrEmitter.cpp | 276 +++++++++++-------
5 files changed, 249 insertions(+), 270 deletions(-)
diff --git a/clang/include/clang/Basic/AttributeCommonInfo.h b/clang/include/clang/Basic/AttributeCommonInfo.h
index cdf9dcaff7508..5f024b4b5fd78 100644
--- a/clang/include/clang/Basic/AttributeCommonInfo.h
+++ b/clang/include/clang/Basic/AttributeCommonInfo.h
@@ -191,12 +191,6 @@ class AttributeCommonInfo {
/// __gnu__::__attr__ will be normalized to gnu::attr).
std::string getNormalizedFullName() const;
- /// Generate a normalized full name, with syntax, scope and name.
- static std::string
- normalizeFullNameWithSyntax(const IdentifierInfo *Name,
- const IdentifierInfo *Scope,
- AttributeCommonInfo::Syntax SyntaxUsed);
-
bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec; }
bool isMicrosoftAttribute() const { return SyntaxUsed == AS_Microsoft; }
diff --git a/clang/lib/Basic/Attributes.cpp b/clang/lib/Basic/Attributes.cpp
index a39eb85f7e8fa..867d241a2cf84 100644
--- a/clang/lib/Basic/Attributes.cpp
+++ b/clang/lib/Basic/Attributes.cpp
@@ -153,40 +153,6 @@ std::string AttributeCommonInfo::getNormalizedFullName() const {
normalizeName(getAttrName(), getScopeName(), getSyntax()));
}
-static StringRef getSyntaxName(AttributeCommonInfo::Syntax SyntaxUsed) {
- switch (SyntaxUsed) {
- case AttributeCommonInfo::AS_GNU:
- return "GNU";
- case AttributeCommonInfo::AS_CXX11:
- return "CXX11";
- case AttributeCommonInfo::AS_C23:
- return "C23";
- case AttributeCommonInfo::AS_Declspec:
- return "Declspec";
- case AttributeCommonInfo::AS_Microsoft:
- return "Microsoft";
- case AttributeCommonInfo::AS_Keyword:
- return "Keyword";
- case AttributeCommonInfo::AS_Pragma:
- return "Pragma";
- case AttributeCommonInfo::AS_ContextSensitiveKeyword:
- return "ContextSensitiveKeyword";
- case AttributeCommonInfo::AS_HLSLAnnotation:
- return "HLSLAnnotation";
- case AttributeCommonInfo::AS_Implicit:
- return "Implicit";
- }
- llvm_unreachable("Invalid attribute syntax");
-}
-
-std::string AttributeCommonInfo::normalizeFullNameWithSyntax(
- const IdentifierInfo *Name, const IdentifierInfo *ScopeName,
- Syntax SyntaxUsed) {
- return (Twine(getSyntaxName(SyntaxUsed)) +
- "::" + normalizeName(Name, ScopeName, SyntaxUsed))
- .str();
-}
-
unsigned AttributeCommonInfo::calculateAttributeSpellingListIndex() const {
// Both variables will be used in tablegen generated
// attribute spell list index matching code.
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 4a2d9a650e20c..719dec1422b69 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -314,27 +314,24 @@ void Parser::ParseGNUAttributes(ParsedAttributes &Attrs,
}
/// Determine whether the given attribute has an identifier argument.
-static bool attributeHasIdentifierArg(const IdentifierInfo &II,
+static bool attributeHasIdentifierArg(const llvm::Triple &T,
+ const IdentifierInfo &II,
ParsedAttr::Syntax Syntax,
IdentifierInfo *ScopeName) {
- std::string FullName =
- AttributeCommonInfo::normalizeFullNameWithSyntax(&II, ScopeName, Syntax);
#define CLANG_ATTR_IDENTIFIER_ARG_LIST
- return llvm::StringSwitch<bool>(FullName)
+ return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
#include "clang/Parse/AttrParserStringSwitches.inc"
.Default(false);
#undef CLANG_ATTR_IDENTIFIER_ARG_LIST
}
-/// Determine whether the given attribute has an identifier argument.
+/// Determine whether the given attribute has string arguments.
static ParsedAttributeArgumentsProperties
attributeStringLiteralListArg(const llvm::Triple &T, const IdentifierInfo &II,
ParsedAttr::Syntax Syntax,
IdentifierInfo *ScopeName) {
- std::string FullName =
- AttributeCommonInfo::normalizeFullNameWithSyntax(&II, ScopeName, Syntax);
#define CLANG_ATTR_STRING_LITERAL_ARG_LIST
- return llvm::StringSwitch<uint32_t>(FullName)
+ return llvm::StringSwitch<uint32_t>(normalizeAttrName(II.getName()))
#include "clang/Parse/AttrParserStringSwitches.inc"
.Default(0);
#undef CLANG_ATTR_STRING_LITERAL_ARG_LIST
@@ -344,10 +341,8 @@ attributeStringLiteralListArg(const llvm::Triple &T, const IdentifierInfo &II,
static bool attributeHasVariadicIdentifierArg(const IdentifierInfo &II,
ParsedAttr::Syntax Syntax,
IdentifierInfo *ScopeName) {
- std::string FullName =
- AttributeCommonInfo::normalizeFullNameWithSyntax(&II, ScopeName, Syntax);
#define CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST
- return llvm::StringSwitch<bool>(FullName)
+ return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
#include "clang/Parse/AttrParserStringSwitches.inc"
.Default(false);
#undef CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST
@@ -357,10 +352,8 @@ static bool attributeHasVariadicIdentifierArg(const IdentifierInfo &II,
static bool attributeTreatsKeywordThisAsIdentifier(const IdentifierInfo &II,
ParsedAttr::Syntax Syntax,
IdentifierInfo *ScopeName) {
- std::string FullName =
- AttributeCommonInfo::normalizeFullNameWithSyntax(&II, ScopeName, Syntax);
#define CLANG_ATTR_THIS_ISA_IDENTIFIER_ARG_LIST
- return llvm::StringSwitch<bool>(FullName)
+ return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
#include "clang/Parse/AttrParserStringSwitches.inc"
.Default(false);
#undef CLANG_ATTR_THIS_ISA_IDENTIFIER_ARG_LIST
@@ -370,10 +363,8 @@ static bool attributeTreatsKeywordThisAsIdentifier(const IdentifierInfo &II,
static bool attributeAcceptsExprPack(const IdentifierInfo &II,
ParsedAttr::Syntax Syntax,
IdentifierInfo *ScopeName) {
- std::string FullName =
- AttributeCommonInfo::normalizeFullNameWithSyntax(&II, ScopeName, Syntax);
#define CLANG_ATTR_ACCEPTS_EXPR_PACK
- return llvm::StringSwitch<bool>(FullName)
+ return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
#include "clang/Parse/AttrParserStringSwitches.inc"
.Default(false);
#undef CLANG_ATTR_ACCEPTS_EXPR_PACK
@@ -383,42 +374,22 @@ static bool attributeAcceptsExprPack(const IdentifierInfo &II,
static bool attributeIsTypeArgAttr(const IdentifierInfo &II,
ParsedAttr::Syntax Syntax,
IdentifierInfo *ScopeName) {
- std::string FullName =
- AttributeCommonInfo::normalizeFullNameWithSyntax(&II, ScopeName, Syntax);
#define CLANG_ATTR_TYPE_ARG_LIST
- return llvm::StringSwitch<bool>(FullName)
+ return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
#include "clang/Parse/AttrParserStringSwitches.inc"
.Default(false);
#undef CLANG_ATTR_TYPE_ARG_LIST
}
-/// Determine whether the given attribute takes identifier arguments.
+/// Determine whether the given attribute takes a strict identifier argument.
static bool attributeHasStrictIdentifierArgs(const IdentifierInfo &II,
ParsedAttr::Syntax Syntax,
IdentifierInfo *ScopeName) {
- std::string FullName =
- AttributeCommonInfo::normalizeFullNameWithSyntax(&II, ScopeName, Syntax);
-#define CLANG_ATTR_STRICT_IDENTIFIER_ARG_AT_INDEX_LIST
- return (llvm::StringSwitch<uint64_t>(FullName)
-#include "clang/Parse/AttrParserStringSwitches.inc"
- .Default(0)) != 0;
-#undef CLANG_ATTR_STRICT_IDENTIFIER_ARG_AT_INDEX_LIST
-}
-
-/// Determine whether the given attribute takes an identifier argument at a
-/// specific index
-static bool attributeHasStrictIdentifierArgAtIndex(const IdentifierInfo &II,
- ParsedAttr::Syntax Syntax,
- IdentifierInfo *ScopeName,
- size_t argIndex) {
- std::string FullName =
- AttributeCommonInfo::normalizeFullNameWithSyntax(&II, ScopeName, Syntax);
-#define CLANG_ATTR_STRICT_IDENTIFIER_ARG_AT_INDEX_LIST
- return (llvm::StringSwitch<uint64_t>(FullName)
+#define CLANG_ATTR_STRICT_IDENTIFIER_ARG_LIST
+ return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
#include "clang/Parse/AttrParserStringSwitches.inc"
- .Default(0)) &
- (1ull << argIndex);
-#undef CLANG_ATTR_STRICT_IDENTIFIER_ARG_AT_INDEX_LIST
+ .Default(false);
+#undef CLANG_ATTR_STRICT_IDENTIFIER_ARG_LIST
}
/// Determine whether the given attribute requires parsing its arguments
@@ -426,10 +397,8 @@ static bool attributeHasStrictIdentifierArgAtIndex(const IdentifierInfo &II,
static bool attributeParsedArgsUnevaluated(const IdentifierInfo &II,
ParsedAttr::Syntax Syntax,
IdentifierInfo *ScopeName) {
- std::string FullName =
- AttributeCommonInfo::normalizeFullNameWithSyntax(&II, ScopeName, Syntax);
#define CLANG_ATTR_ARG_CONTEXT_LIST
- return llvm::StringSwitch<bool>(FullName)
+ return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
#include "clang/Parse/AttrParserStringSwitches.inc"
.Default(false);
#undef CLANG_ATTR_ARG_CONTEXT_LIST
@@ -575,7 +544,8 @@ unsigned Parser::ParseAttributeArgsCommon(
// If this attribute wants an 'identifier' argument, make it so.
bool IsIdentifierArg =
AttributeHasVariadicIdentifierArg ||
- attributeHasIdentifierArg(*AttrName, Form.getSyntax(), ScopeName);
+ attributeHasIdentifierArg(getTargetInfo().getTriple(), *AttrName,
+ Form.getSyntax(), ScopeName);
ParsedAttr::Kind AttrKind =
ParsedAttr::getParsedKind(AttrName, ScopeName, Form.getSyntax());
@@ -619,13 +589,6 @@ unsigned Parser::ParseAttributeArgsCommon(
if (ChangeKWThisToIdent && Tok.is(tok::kw_this))
Tok.setKind(tok::identifier);
- if (Tok.is(tok::identifier) &&
- attributeHasStrictIdentifierArgAtIndex(
- *AttrName, Form.getSyntax(), ScopeName, ArgExprs.size())) {
- ArgExprs.push_back(ParseIdentifierLoc());
- continue;
- }
-
ExprResult ArgExpr;
if (Tok.is(tok::identifier)) {
ArgExprs.push_back(ParseIdentifierLoc());
diff --git a/clang/test/TableGen/attrs-parser-string-switches.td b/clang/test/TableGen/attrs-parser-string-switches.td
index c15ab104e0ccd..3219916869004 100644
--- a/clang/test/TableGen/attrs-parser-string-switches.td
+++ b/clang/test/TableGen/attrs-parser-string-switches.td
@@ -22,19 +22,15 @@ def TestUnEvalTwo : InheritableAttr {
}
// CHECK: #if defined(CLANG_ATTR_ARG_CONTEXT_LIST)
-// CHECK-NOT: .Case("Pragma::test_uneval", true)
-// CHECK: .Case("GNU::test_uneval", true)
-// CHECK-NOT: .Case("Pragma::test_uneval", true)
-// CHECK: .Case("CXX11::clang::test_uneval", true)
-// CHECK-NOT: .Case("Pragma::test_uneval", true)
-// CHECK: .Case("C23::clang::test_uneval", true)
-// CHECK-NOT: .Case("Pragma::test_uneval", true)
+// CHECK: .Case("test_uneval", (Syntax==AttributeCommonInfo::AS_GNU && !ScopeName) ? 1 :
+// CHECK-SAME: (Syntax==AttributeCommonInfo::AS_CXX11 && ScopeName && ScopeName->getName()=="clang") ? 1 :
+// CHECK-SAME: (Syntax==AttributeCommonInfo::AS_C23 && ScopeName && ScopeName->getName()=="clang") ? 1 : 0)
// CHECK: #endif // CLANG_ATTR_ARG_CONTEXT_LIST
// Test attributeHasIdentifierArg: Same spelling, one with and one without
// an IdentifierArg.
def TestIdentOne : Attr {
- let Spellings = [Clang<"test_ident">];
+ let Spellings = [GNU<"test_ident">];
let Args = [EnumArgument<"Option", "OptionType", /*is_string=*/false,
["optA", "optB"], ["OPTA", "OPTB"]>];
let Subjects = SubjectList<[Function]>;
@@ -48,28 +44,35 @@ def TestIdentTwo : StmtAttr {
let Documentation = [Undocumented];
}
+// Checks that the simple value is produced if only one attribute with a
+// spelling.
+def TestOnlyIdent : Attr {
+ let Spellings = [GNU<"test_only_ident">];
+ let Args = [EnumArgument<"Option", "OptionType", /*is_string=*/false,
+ ["optA", "optB"], ["OPTA", "OPTB"]>];
+ let Subjects = SubjectList<[Function]>;
+ let Documentation = [Undocumented];
+}
+
// CHECK: #if defined(CLANG_ATTR_IDENTIFIER_ARG_LIST)
-// CHECK-NOT: .Case("Pragma::test_ident", true)
-// CHECK: .Case("GNU::test_ident", true)
-// CHECK-NOT: .Case("Pragma::test_ident", true)
-// CHECK: .Case("CXX11::clang::test_ident", true)
-// CHECK-NOT: .Case("Pragma::test_ident", true)
-// CHECK: .Case("C23::clang::test_ident", true)
-// CHECK-NOT: .Case("Pragma::test_ident", true)
+// CHECK: .Case("test_ident", (Syntax==AttributeCommonInfo::AS_GNU && !ScopeName)
+// CHECK: .Case("test_only_ident", true)
+// CHECK: .Case("test_targspec",
+// CHECK-SAME: (T.getArch() == llvm::Triple::arm)) ? 1 : 0
// CHECK: #endif // CLANG_ATTR_IDENTIFIER_ARG_LIST
// Test attributeStringLiteralListArg : Same spelling, some with a
// StringArgument, some without, some in different locations.
def TestStringOne : DeclOrTypeAttr {
let Spellings = [Clang<"test_string">];
- let Args = [StringArgument<"strarg">];
+ let Args = [UnsignedArgument<"unsarg">];
let Subjects = SubjectList<[Function, TypedefName, ParmVar]>;
let Documentation = [AcquireHandleDocs];
}
def TestStringTwo : InheritableAttr {
let Spellings = [Pragma<"", "test_string">];
- let Args = [UnsignedArgument<"unsarg">];
+ let Args = [StringArgument<"strarg">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [Undocumented];
}
@@ -83,39 +86,31 @@ def TestStringThree : Attr {
}
// CHECK: #if defined(CLANG_ATTR_STRING_LITERAL_ARG_LIST)
-// CHECK-NOT: .Case("Pragma::test_string"
-// CHECK: .Case("GNU::test_string", 1)
-// CHECK: .Case("CXX11::clang::test_string", 1)
-// CHECK: .Case("C23::clang::test_string", 1)
-// CHECK-NOT: .Case("Pragma::test_string"
-// CHECK: .Case("Declspec::test_string", 2)
-// CHECK-NOT: .Case("Pragma::test_string"
+// CHECK: .Case("test_string", (Syntax==AttributeCommonInfo::AS_Declspec && !ScopeName) ? 2 :
+// CHECK-SAME: (Syntax==AttributeCommonInfo::AS_Pragma && !ScopeName) ? 1 : 0)
+// CHECK: .Case("test_targspec",
+// CHECK-SAME: (T.getArch() == llvm::Triple::arm)) ? 4294967294 :
+// CHECK-SAME: (T.getArch() == llvm::Triple::ppc)) ? 1 :
// CHECK: #endif // CLANG_ATTR_STRING_LITERAL_ARG_LIST
// Test attributeHasVariadicIdentifierArg : One with VariadicIdentifierArgument
// and one without.
def TestVariadicIdentOne : InheritableAttr {
let Spellings = [Clang<"test_var_ident">];
- let Args = [VariadicIdentifierArgument<"iargs">];
+ let Args = [UnsignedArgument<"Hint">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [Undocumented];
}
def TestVariadicIdentTwo : InheritableAttr {
let Spellings = [Pragma<"", "test_var_ident">];
- let Args = [UnsignedArgument<"Hint">];
+ let Args = [VariadicIdentifierArgument<"iargs">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [Undocumented];
}
// CHECK: #if defined(CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST)
-// CHECK-NOT: .Case("Pragma::"test_var_ident", true)
-// CHECK: .Case("GNU::test_var_ident", true)
-// CHECK-NOT: .Case("Pragma::test_var_ident", true)
-// CHECK: .Case("CXX11::clang::test_var_ident", true)
-// CHECK-NOT: .Case("Pragma::test_var_ident", true)
-// CHECK: .Case("C23::clang::test_var_ident", true)
-// CHECK-NOT: .Case("Pragma::test_var_ident", true)
+// CHECK: .Case("test_var_ident", (Syntax==AttributeCommonInfo::AS_Pragma && !ScopeName))
// CHECK: #endif // CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST
// Test attributeTreatsKeywordThisAsIdentifier : Same spelling, one with and
@@ -135,13 +130,9 @@ def TestVarOrIdxTwo : InheritableAttr {
}
// CHECK: #if defined(CLANG_ATTR_THIS_ISA_IDENTIFIER_ARG_LIST)
-// CHECK-NOT: .Case("Pragma::test_var_idx", true)
-// CHECK: .Case("GNU::test_var_idx", true)
-// CHECK-NOT: .Case("Pragma::test_var_idx", true)
-// CHECK: .Case("CXX11::clang::test_var_idx", true)
-// CHECK-NOT: .Case("Pragma::test_var_idx", true)
-// CHECK: .Case("C23::clang::test_var_idx", true)
-// CHECK-NOT: .Case("Pragma::test_var_idx", true)
+// CHECK: .Case("test_var_idx", (Syntax==AttributeCommonInfo::AS_GNU && !ScopeName) ? 1 :
+// CHECK-SAME: (Syntax==AttributeCommonInfo::AS_CXX11 && ScopeName && ScopeName->getName()=="clang") ? 1 :
+// CHECK-SAME: (Syntax==AttributeCommonInfo::AS_C23 && ScopeName && ScopeName->getName()=="clang") ? 1 : 0)
// CHECK: #endif // CLANG_ATTR_THIS_ISA_IDENTIFIER_ARG_LIST
// Test attributeAcceptsExprPack : One with, one without.
@@ -161,13 +152,9 @@ def TestExprPackTwo : InheritableAttr {
}
// CHECK: #if defined(CLANG_ATTR_ACCEPTS_EXPR_PACK)
-// CHECK-NOT: .Case("Pragma::test_expr_pack", true)
-// CHECK: .Case("GNU::test_expr_pack", true)
-// CHECK-NOT: .Case("Pragma::test_expr_pack", true)
-// CHECK: .Case("CXX11::clang::test_expr_pack", true)
-// CHECK-NOT: .Case("Pragma::test_expr_pack", true)
-// CHECK: .Case("C23::clang::test_expr_pack", true)
-// CHECK-NOT: .Case("Pragma::test_expr_pack", true)
+// CHECK: .Case("test_expr_pack", (Syntax==AttributeCommonInfo::AS_GNU && !ScopeName) ? 1 :
+// CHECK-SAME: (Syntax==AttributeCommonInfo::AS_CXX11 && ScopeName && ScopeName->getName()=="clang") ? 1 :
+// CHECK-SAME: (Syntax==AttributeCommonInfo::AS_C23 && ScopeName && ScopeName->getName()=="clang") ? 1 : 0)
// CHECK: #endif // CLANG_ATTR_ACCEPTS_EXPR_PACK
@@ -188,17 +175,12 @@ def TestTypeTwo : InheritableAttr {
}
// CHECK: #if defined(CLANG_ATTR_TYPE_ARG_LIST)
-// CHECK-NOT: .Case("Pragma::test_type", true)
-// CHECK: .Case("GNU::test_type", true)
-// CHECK-NOT: .Case("Pragma::test_type", true)
-// CHECK: .Case("CXX11::clang::test_type", true)
-// CHECK-NOT: .Case("Pragma::test_type", true)
-// CHECK: .Case("C23::clang::test_type", true)
-// CHECK-NOT: .Case("Pragma::test_type", true)
+// CHECK: .Case("test_type", (Syntax==AttributeCommonInfo::AS_GNU && !ScopeName) ? 1 :
+// CHECK-SAME: (Syntax==AttributeCommonInfo::AS_CXX11 && ScopeName && ScopeName->getName()=="clang") ? 1 :
+// CHECK-SAME: (Syntax==AttributeCommonInfo::AS_C23 && ScopeName && ScopeName->getName()=="clang") ? 1 : 0)
// CHECK: #endif // CLANG_ATTR_TYPE_ARG_LIST
-// Test attributeHasStrictIdentifierArgs and
-// attributeHasStrictIdentifierArgAtIndex, one used StrictEnumParameters, the
+// Test attributeHasStrictIdentifierArgs, one used StrictEnumParameters, the
// other does not.
def TestStrictEnumOne : InheritableAttr {
let Spellings = [Clang<"strict_enum">];
@@ -221,12 +203,32 @@ def TestStrictEnumTwo : InheritableAttr {
let Documentation = [Undocumented];
}
-// CHECK: #if defined(CLANG_ATTR_STRICT_IDENTIFIER_ARG_AT_INDEX_LIST)
-// CHECK-NOT: .Case("Pragma::strict_enum", 5ull)
-// CHECK: .Case("GNU::strict_enum", 5ull)
-// CHECK-NOT: .Case("Pragma::strict_enum", 5ull)
-// CHECK: .Case("CXX11::clang::strict_enum", 5ull)
-// CHECK-NOT: .Case("Pragma::strict_enum", 5ull)
-// CHECK: .Case("C23::clang::strict_enum", 5ull)
-// CHECK-NOT: .Case("Pragma::strict_enum", 5ull)
-// CHECK: #endif // CLANG_ATTR_STRICT_IDENTIFIER_ARG_AT_INDEX_LIST
+// CHECK: #if defined(CLANG_ATTR_STRICT_IDENTIFIER_ARG_LIST)
+// CHECK: .Case("strict_enum", (Syntax==AttributeCommonInfo::AS_GNU && !ScopeName) ? 1 :
+// CHECK-SAME: (Syntax==AttributeCommonInfo::AS_CXX11 && ScopeName && ScopeName->getName()=="clang") ? 1 :
+// CHECK-SAME: (Syntax==AttributeCommonInfo::AS_C23 && ScopeName && ScopeName->getName()=="clang") ? 1 : 0)
+// CHECK: #endif // CLANG_ATTR_STRICT_IDENTIFIER_ARG_LIST
+
+// Test that TargetSpecific attributes work as expected.
+
+def TargSpecX86 : InheritableAttr, TargetSpecificAttr<TargetArch<["x86"]>> {
+ let Spellings = [GCC<"test_targspec">];
+ let Subjects = SubjectList<[Function]>;
+ let Args = [UnsignedArgument<"ua">, DefaultIntArgument<"o", 0>];
+ let ParseKind = "TargSpec";
+ let Documentation = [Undocumented];
+}
+def TargSpecPPC : InheritableAttr, TargetSpecificAttr<TargetArch<["ppc"]>> {
+ let Spellings = [GCC<"test_targspec">];
+ let Subjects = SubjectList<[Function]>;
+ let Args = [StringArgument<"str">, VariadicExprArgument<"args">];
+ let ParseKind = "TargSpec";
+ let Documentation = [Undocumented];
+}
+def TargSpecARM : InheritableAttr, TargetSpecificAttr<TargetArch<["arm"]>> {
+ let Spellings = [GCC<"test_targspec">];
+ let Subjects = SubjectList<[Function]>;
+ let Args = [IdentifierArgument<"id">, VariadicStringArgument<"sargs">];
+ let ParseKind = "TargSpec";
+ let Documentation = [Undocumented];
+}
diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp
index f504b1de144b7..9331dcca8ec14 100644
--- a/clang/utils/TableGen/ClangAttrEmitter.cpp
+++ b/clang/utils/TableGen/ClangAttrEmitter.cpp
@@ -76,8 +76,27 @@ class FlattenedSpelling {
const Record &getSpellingRecord() const { return OriginalSpelling; }
};
+struct FlattenedSpellingInfo {
+ FlattenedSpellingInfo(std::string Syntax, std::string Scope,
+ std::string TargetTest, uint32_t ArgMask)
+ : Syntax(Syntax), Scope(Scope), TargetTest(TargetTest),
+ ArgMask(ArgMask) {}
+ std::string Syntax;
+ std::string Scope;
+ std::string TargetTest;
+ uint32_t ArgMask;
+};
+using FSIVecTy = std::vector<FlattenedSpellingInfo>;
+
} // end anonymous namespace
+static bool GenerateTargetSpecificAttrChecks(const Record *R,
+ std::vector<StringRef> &Arches,
+ std::string &Test,
+ std::string *FnName);
+static bool isStringLiteralArgument(const Record *Arg);
+static bool isVariadicStringLiteralArgument(const Record *Arg);
+
static std::vector<FlattenedSpelling>
GetFlattenedSpellings(const Record &Attr) {
std::vector<Record *> Spellings = Attr.getValueAsListOfDefs("Spellings");
@@ -2379,6 +2398,113 @@ template <typename Fn> static void forEachSpelling(const Record &Attr, Fn &&F) {
}
}
+std::map<std::string, std::vector<const Record *>> NameToAttrsMap;
+
+/// Build a map from the attribute name to the Attrs that use that name. If more
+/// than one Attr use a name, the arguments could be different so a more complex
+/// check is needed in the generated switch.
+void generateNameToAttrsMap(RecordKeeper &Records) {
+ std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
+ for (const auto *A : Attrs) {
+ std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*A);
+ for (const auto &S : Spellings) {
+ auto It = NameToAttrsMap.find(S.name());
+ if (It != NameToAttrsMap.end()) {
+ if (llvm::none_of(It->second, [&](const Record *R) { return R == A; }))
+ It->second.emplace_back(A);
+ } else {
+ std::vector<const Record *> V;
+ V.emplace_back(A);
+ NameToAttrsMap.insert(std::make_pair(S.name(), V));
+ }
+ }
+ }
+}
+
+/// Generate the info needed to produce the case values in case more than one
+/// attribute has the same name. Store the info in a map that can be processed
+/// after all attributes are seen.
+static void generateFlattenedSpellingInfo(const Record &Attr,
+ std::map<std::string, FSIVecTy> &Map,
+ uint32_t ArgMask = 0) {
+ std::string TargetTest;
+ if (Attr.isSubClassOf("TargetSpecificAttr") &&
+ !Attr.isValueUnset("ParseKind")) {
+ const Record *T = Attr.getValueAsDef("Target");
+ std::vector<StringRef> Arches = T->getValueAsListOfStrings("Arches");
+ (void)GenerateTargetSpecificAttrChecks(T, Arches, TargetTest, nullptr);
+ }
+
+ forEachSpelling(Attr, [&](const FlattenedSpelling &S) {
+ auto It = Map.find(S.name());
+ if (It != Map.end()) {
+ It->second.emplace_back(S.variety(), S.nameSpace(), TargetTest,
+ ArgMask);
+ } else {
+ FSIVecTy V;
+ V.emplace_back(S.variety(), S.nameSpace(), TargetTest, ArgMask);
+ Map.insert(std::make_pair(S.name(), V));
+ }
+ });
+}
+
+static bool nameAppliesToOneAttribute(std::string Name) {
+ auto It = NameToAttrsMap.find(Name);
+ assert(It != NameToAttrsMap.end());
+ return It->second.size() == 1;
+}
+
+static bool emitIfSimpleValue(std::string Name, uint32_t ArgMask,
+ raw_ostream &OS) {
+ if (nameAppliesToOneAttribute(Name)) {
+ OS << ".Case(\"" << Name << "\", ";
+ if (ArgMask != 0)
+ OS << ArgMask << ")\n";
+ else
+ OS << "true)\n";
+ return true;
+ }
+ return false;
+}
+
+static void emitSingleCondition(const FlattenedSpellingInfo &FSI,
+ raw_ostream &OS) {
+ OS << "(Syntax==AttributeCommonInfo::AS_" << FSI.Syntax << " && ";
+ if (!FSI.Scope.empty())
+ OS << "ScopeName && ScopeName->getName()==\"" << FSI.Scope << "\"";
+ else
+ OS << "!ScopeName";
+ if (!FSI.TargetTest.empty())
+ OS << " && " << FSI.TargetTest;
+ OS << ")";
+}
+
+static void emitStringSwitchCases(std::map<std::string, FSIVecTy> &Map,
+ raw_ostream &OS) {
+ for (const auto& P : Map) {
+ if (emitIfSimpleValue(P.first, P.second[0].ArgMask, OS))
+ continue;
+
+ // Not simple, build expressions for each case.
+ StringRef Name = P.first;
+ const FSIVecTy &Vec = P.second;
+ OS << ".Case(\"" << Name << "\", ";
+ for (unsigned I = 0, E = Vec.size(); I < E; ++I) {
+ emitSingleCondition(Vec[I], OS);
+ uint32_t ArgMask = Vec[I].ArgMask;
+ if (E == 1 && ArgMask == 0)
+ continue;
+
+ // More than one or it's the Mask form. Create a conditional expression.
+ uint32_t SuccessValue = ArgMask != 0 ? ArgMask : 1;
+ OS << " ? " << SuccessValue << " : ";
+ if (I == E - 1)
+ OS << 0;
+ }
+ OS << ")\n";
+ }
+}
+
static bool isTypeArgument(const Record *Arg) {
return !Arg->getSuperClasses().empty() &&
Arg->getSuperClasses().back().first->getName() == "TypeArgument";
@@ -2387,6 +2513,7 @@ static bool isTypeArgument(const Record *Arg) {
/// Emits the first-argument-is-type property for attributes.
static void emitClangAttrTypeArgList(RecordKeeper &Records, raw_ostream &OS) {
OS << "#if defined(CLANG_ATTR_TYPE_ARG_LIST)\n";
+ std::map<std::string, FSIVecTy> FSIMap;
std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
for (const auto *Attr : Attrs) {
@@ -2397,15 +2524,9 @@ static void emitClangAttrTypeArgList(RecordKeeper &Records, raw_ostream &OS) {
if (!isTypeArgument(Args[0]))
continue;
-
- // All these spellings take a single type argument.
- forEachSpelling(*Attr, [&](const FlattenedSpelling &S) {
- OS << ".Case(\"" << S.variety();
- if (S.nameSpace().length())
- OS << "::" << S.nameSpace();
- OS << "::" << S.name() << "\", true)\n";
- });
+ generateFlattenedSpellingInfo(*Attr, FSIMap);
}
+ emitStringSwitchCases(FSIMap, OS);
OS << "#endif // CLANG_ATTR_TYPE_ARG_LIST\n\n";
}
@@ -2413,21 +2534,16 @@ static void emitClangAttrTypeArgList(RecordKeeper &Records, raw_ostream &OS) {
/// attributes.
static void emitClangAttrArgContextList(RecordKeeper &Records, raw_ostream &OS) {
OS << "#if defined(CLANG_ATTR_ARG_CONTEXT_LIST)\n";
+ std::map<std::string, FSIVecTy> FSIMap;
ParsedAttrMap Attrs = getParsedAttrList(Records);
for (const auto &I : Attrs) {
const Record &Attr = *I.second;
if (!Attr.getValueAsBit("ParseArgumentsAsUnevaluated"))
continue;
-
- // All these spellings take are parsed unevaluated.
- forEachSpelling(Attr, [&](const FlattenedSpelling &S) {
- OS << ".Case(\"" << S.variety();
- if (S.nameSpace().length())
- OS << "::" << S.nameSpace();
- OS << "::" << S.name() << "\", true)\n";
- });
+ generateFlattenedSpellingInfo(Attr, FSIMap);
}
+ emitStringSwitchCases(FSIMap, OS);
OS << "#endif // CLANG_ATTR_ARG_CONTEXT_LIST\n\n";
}
@@ -2479,28 +2595,18 @@ static void emitClangAttrVariadicIdentifierArgList(RecordKeeper &Records,
raw_ostream &OS) {
OS << "#if defined(CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST)\n";
std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
+ std::map<std::string, FSIVecTy> FSIMap;
for (const auto *A : Attrs) {
// Determine whether the first argument is a variadic identifier.
std::vector<Record *> Args = A->getValueAsListOfDefs("Args");
if (Args.empty() || !isVariadicIdentifierArgument(Args[0]))
continue;
-
- // All these spellings take an identifier argument.
- forEachSpelling(*A, [&](const FlattenedSpelling &S) {
- OS << ".Case(\"" << S.variety();
- if (S.nameSpace().length())
- OS << "::" << S.nameSpace();
- OS << "::" << S.name() << "\", true)\n";
- });
+ generateFlattenedSpellingInfo(*A, FSIMap);
}
+ emitStringSwitchCases(FSIMap, OS);
OS << "#endif // CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST\n\n";
}
-static bool GenerateTargetSpecificAttrChecks(const Record *R,
- std::vector<StringRef> &Arches,
- std::string &Test,
- std::string *FnName);
-
// Emits the list of arguments that should be parsed as unevaluated string
// literals for each attribute.
static void emitClangAttrUnevaluatedStringLiteralList(RecordKeeper &Records,
@@ -2521,48 +2627,16 @@ static void emitClangAttrUnevaluatedStringLiteralList(RecordKeeper &Records,
return Bits;
};
- auto AddMaskWithTargetCheck = [](const Record *Attr, uint32_t Mask,
- std::string &MaskStr) {
- const Record *T = Attr->getValueAsDef("Target");
- std::vector<StringRef> Arches = T->getValueAsListOfStrings("Arches");
- std::string Test;
- GenerateTargetSpecificAttrChecks(T, Arches, Test, nullptr);
- MaskStr.append(Test + " ? " + std::to_string(Mask) + " : ");
- };
-
- ParsedAttrMap Dupes;
- ParsedAttrMap Attrs = getParsedAttrList(Records, &Dupes, /*SemaOnly=*/false);
- for (const auto &[AttrName, Attr] : Attrs) {
- std::string MaskStr;
- if (Attr->isSubClassOf("TargetSpecificAttr") &&
- !Attr->isValueUnset("ParseKind")) {
- if (uint32_t Mask = MakeMask(Attr->getValueAsListOfDefs("Args")))
- AddMaskWithTargetCheck(Attr, Mask, MaskStr);
- StringRef ParseKind = Attr->getValueAsString("ParseKind");
- for (const auto &[DupeParseKind, DupAttr] : Dupes) {
- if (DupeParseKind != ParseKind)
- continue;
- if (uint32_t Mask = MakeMask(DupAttr->getValueAsListOfDefs("Args")))
- AddMaskWithTargetCheck(DupAttr, Mask, MaskStr);
- }
- if (!MaskStr.empty())
- MaskStr.append("0");
- } else {
- if (uint32_t Mask = MakeMask(Attr->getValueAsListOfDefs("Args")))
- MaskStr = std::to_string(Mask);
- }
-
- if (MaskStr.empty())
+ std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
+ std::map<std::string, FSIVecTy> FSIMap;
+ for (const auto *Attr : Attrs) {
+ // Determine whether there are any string arguments.
+ uint32_t ArgMask = MakeMask(Attr->getValueAsListOfDefs("Args"));
+ if (!ArgMask)
continue;
-
- // All these spellings have at least one string literal has argument.
- forEachSpelling(*Attr, [&](const FlattenedSpelling &S) {
- OS << ".Case(\"" << S.variety();
- if (S.nameSpace().length())
- OS << "::" << S.nameSpace();
- OS << "::" << S.name() << "\", " << MaskStr << ")\n";
- });
+ generateFlattenedSpellingInfo(*Attr, FSIMap, ArgMask);
}
+ emitStringSwitchCases(FSIMap, OS);
OS << "#endif // CLANG_ATTR_STRING_LITERAL_ARG_LIST\n\n";
}
@@ -2571,49 +2645,37 @@ static void emitClangAttrIdentifierArgList(RecordKeeper &Records, raw_ostream &O
OS << "#if defined(CLANG_ATTR_IDENTIFIER_ARG_LIST)\n";
std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
+ std::map<std::string, FSIVecTy> FSIMap;
for (const auto *Attr : Attrs) {
// Determine whether the first argument is an identifier.
std::vector<Record *> Args = Attr->getValueAsListOfDefs("Args");
if (Args.empty() || !isIdentifierArgument(Args[0]))
continue;
-
- // All these spellings take an identifier argument.
- forEachSpelling(*Attr, [&](const FlattenedSpelling &S) {
- OS << ".Case(\"" << S.variety();
- if (S.nameSpace().length())
- OS << "::" << S.nameSpace();
- OS << "::" << S.name() << "\", true)\n";
- });
+ generateFlattenedSpellingInfo(*Attr, FSIMap);
}
+ emitStringSwitchCases(FSIMap, OS);
OS << "#endif // CLANG_ATTR_IDENTIFIER_ARG_LIST\n\n";
}
-// Emits the indexed-argument-is-identifier property for attributes.
-static void emitClangAttrStrictIdentifierArgAtIndexList(RecordKeeper &Records,
- raw_ostream &OS) {
- OS << "#if defined(CLANG_ATTR_STRICT_IDENTIFIER_ARG_AT_INDEX_LIST)\n";
+// Emits the list for attributes having StrictEnumParameters.
+static void emitClangAttrStrictIdentifierArgList(RecordKeeper &Records,
+ raw_ostream &OS) {
+ OS << "#if defined(CLANG_ATTR_STRICT_IDENTIFIER_ARG_LIST)\n";
std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
+ std::map<std::string, FSIVecTy> FSIMap;
for (const auto *Attr : Attrs) {
if (!Attr->getValueAsBit("StrictEnumParameters"))
continue;
- // Determine whether each argument is an identifier.
+ // Check that there is really an identifier argument.
std::vector<Record *> Args = Attr->getValueAsListOfDefs("Args");
- uint64_t enumAtIndex = 0;
- for (size_t I = 0; I < Args.size(); I++)
- enumAtIndex |= ((uint64_t)isIdentifierArgument(Args[I])) << I;
- if (!enumAtIndex)
+ if (llvm::none_of(Args,
+ [&](Record *R) { return isIdentifierArgument(R); }))
continue;
-
- // All these spellings take an identifier argument.
- forEachSpelling(*Attr, [&](const FlattenedSpelling &S) {
- OS << ".Case(\"" << S.variety();
- if (S.nameSpace().length())
- OS << "::" << S.nameSpace();
- OS << "::" << S.name() << "\", " << enumAtIndex << "ull)\n";
- });
+ generateFlattenedSpellingInfo(*Attr, FSIMap);
}
- OS << "#endif // CLANG_ATTR_STRICT_IDENTIFIER_ARG_AT_INDEX_LIST\n\n";
+ emitStringSwitchCases(FSIMap, OS);
+ OS << "#endif // CLANG_ATTR_STRICT_IDENTIFIER_ARG_LIST\n\n";
}
static bool keywordThisIsaIdentifierInArgument(const Record *Arg) {
@@ -2628,20 +2690,15 @@ static void emitClangAttrThisIsaIdentifierArgList(RecordKeeper &Records,
raw_ostream &OS) {
OS << "#if defined(CLANG_ATTR_THIS_ISA_IDENTIFIER_ARG_LIST)\n";
std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
+ std::map<std::string, FSIVecTy> FSIMap;
for (const auto *A : Attrs) {
// Determine whether the first argument is a variadic identifier.
std::vector<Record *> Args = A->getValueAsListOfDefs("Args");
if (Args.empty() || !keywordThisIsaIdentifierInArgument(Args[0]))
continue;
-
- // All these spellings take an identifier argument.
- forEachSpelling(*A, [&](const FlattenedSpelling &S) {
- OS << ".Case(\"" << S.variety();
- if (S.nameSpace().length())
- OS << "::" << S.nameSpace();
- OS << "::" << S.name() << "\", true)\n";
- });
+ generateFlattenedSpellingInfo(*A, FSIMap);
}
+ emitStringSwitchCases(FSIMap, OS);
OS << "#endif // CLANG_ATTR_THIS_ISA_IDENTIFIER_ARG_LIST\n\n";
}
@@ -2649,19 +2706,15 @@ static void emitClangAttrAcceptsExprPack(RecordKeeper &Records,
raw_ostream &OS) {
OS << "#if defined(CLANG_ATTR_ACCEPTS_EXPR_PACK)\n";
ParsedAttrMap Attrs = getParsedAttrList(Records);
+ std::map<std::string, FSIVecTy> FSIMap;
for (const auto &I : Attrs) {
const Record &Attr = *I.second;
if (!Attr.getValueAsBit("AcceptsExprPack"))
continue;
-
- forEachSpelling(Attr, [&](const FlattenedSpelling &S) {
- OS << ".Case(\"" << S.variety();
- if (S.nameSpace().length())
- OS << "::" << S.nameSpace();
- OS << "::" << S.name() << "\", true)\n";
- });
+ generateFlattenedSpellingInfo(Attr, FSIMap);
}
+ emitStringSwitchCases(FSIMap, OS);
OS << "#endif // CLANG_ATTR_ACCEPTS_EXPR_PACK\n\n";
}
@@ -4991,6 +5044,7 @@ void EmitClangAttrNodeTraverse(RecordKeeper &Records, raw_ostream &OS) {
}
void EmitClangAttrParserStringSwitches(RecordKeeper &Records, raw_ostream &OS) {
+ generateNameToAttrsMap(Records);
emitSourceFileHeader("Parser-related llvm::StringSwitch cases", OS, Records);
emitClangAttrArgContextList(Records, OS);
emitClangAttrIdentifierArgList(Records, OS);
@@ -5001,7 +5055,7 @@ void EmitClangAttrParserStringSwitches(RecordKeeper &Records, raw_ostream &OS) {
emitClangAttrTypeArgList(Records, OS);
emitClangAttrLateParsedList(Records, OS);
emitClangAttrLateParsedExperimentalList(Records, OS);
- emitClangAttrStrictIdentifierArgAtIndexList(Records, OS);
+ emitClangAttrStrictIdentifierArgList(Records, OS);
}
void EmitClangAttrSubjectMatchRulesParserStringSwitches(RecordKeeper &Records,
>From 00d7d304db0581a80f816b58b264608b143bc0ea Mon Sep 17 00:00:00 2001
From: Mike Rice <michael.p.rice at intel.com>
Date: Fri, 2 Aug 2024 15:51:41 -0700
Subject: [PATCH 2/2] Fix format.
---
clang/lib/Parse/ParseDecl.cpp | 2 +-
clang/utils/TableGen/ClangAttrEmitter.cpp | 14 ++++++--------
2 files changed, 7 insertions(+), 9 deletions(-)
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 719dec1422b69..8fdbfb70e732c 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -388,7 +388,7 @@ static bool attributeHasStrictIdentifierArgs(const IdentifierInfo &II,
#define CLANG_ATTR_STRICT_IDENTIFIER_ARG_LIST
return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
#include "clang/Parse/AttrParserStringSwitches.inc"
- .Default(false);
+ .Default(false);
#undef CLANG_ATTR_STRICT_IDENTIFIER_ARG_LIST
}
diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp
index 9331dcca8ec14..adbe6af62d5cb 100644
--- a/clang/utils/TableGen/ClangAttrEmitter.cpp
+++ b/clang/utils/TableGen/ClangAttrEmitter.cpp
@@ -79,8 +79,8 @@ class FlattenedSpelling {
struct FlattenedSpellingInfo {
FlattenedSpellingInfo(std::string Syntax, std::string Scope,
std::string TargetTest, uint32_t ArgMask)
- : Syntax(Syntax), Scope(Scope), TargetTest(TargetTest),
- ArgMask(ArgMask) {}
+ : Syntax(Syntax), Scope(Scope), TargetTest(TargetTest), ArgMask(ArgMask) {
+ }
std::string Syntax;
std::string Scope;
std::string TargetTest;
@@ -2438,8 +2438,7 @@ static void generateFlattenedSpellingInfo(const Record &Attr,
forEachSpelling(Attr, [&](const FlattenedSpelling &S) {
auto It = Map.find(S.name());
if (It != Map.end()) {
- It->second.emplace_back(S.variety(), S.nameSpace(), TargetTest,
- ArgMask);
+ It->second.emplace_back(S.variety(), S.nameSpace(), TargetTest, ArgMask);
} else {
FSIVecTy V;
V.emplace_back(S.variety(), S.nameSpace(), TargetTest, ArgMask);
@@ -2481,7 +2480,7 @@ static void emitSingleCondition(const FlattenedSpellingInfo &FSI,
static void emitStringSwitchCases(std::map<std::string, FSIVecTy> &Map,
raw_ostream &OS) {
- for (const auto& P : Map) {
+ for (const auto &P : Map) {
if (emitIfSimpleValue(P.first, P.second[0].ArgMask, OS))
continue;
@@ -2627,7 +2626,7 @@ static void emitClangAttrUnevaluatedStringLiteralList(RecordKeeper &Records,
return Bits;
};
- std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
+ std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
std::map<std::string, FSIVecTy> FSIMap;
for (const auto *Attr : Attrs) {
// Determine whether there are any string arguments.
@@ -2669,8 +2668,7 @@ static void emitClangAttrStrictIdentifierArgList(RecordKeeper &Records,
continue;
// Check that there is really an identifier argument.
std::vector<Record *> Args = Attr->getValueAsListOfDefs("Args");
- if (llvm::none_of(Args,
- [&](Record *R) { return isIdentifierArgument(R); }))
+ if (llvm::none_of(Args, [&](Record *R) { return isIdentifierArgument(R); }))
continue;
generateFlattenedSpellingInfo(*Attr, FSIMap);
}
More information about the cfe-commits
mailing list