@@ -171,12 +171,13 @@ static StringRef NormalizeGNUAttrSpelling(StringRef AttrSpelling) {
171
171
typedef std::vector<std::pair<std::string, const Record *>> ParsedAttrMap;
172
172
173
173
static ParsedAttrMap getParsedAttrList (const RecordKeeper &Records,
174
- ParsedAttrMap *Dupes = nullptr ) {
174
+ ParsedAttrMap *Dupes = nullptr ,
175
+ bool SemaOnly = true ) {
175
176
std::vector<Record *> Attrs = Records.getAllDerivedDefinitions (" Attr" );
176
177
std::set<std::string> Seen;
177
178
ParsedAttrMap R;
178
179
for (const auto *Attr : Attrs) {
179
- if (Attr->getValueAsBit (" SemaHandler" )) {
180
+ if (!SemaOnly || Attr->getValueAsBit (" SemaHandler" )) {
180
181
std::string AN;
181
182
if (Attr->isSubClassOf (" TargetSpecificAttr" ) &&
182
183
!Attr->isValueUnset (" ParseKind" )) {
@@ -2358,19 +2359,21 @@ static bool isVariadicExprArgument(const Record *Arg) {
2358
2359
}
2359
2360
2360
2361
static bool isStringLiteralArgument (const Record *Arg) {
2361
- return !Arg->getSuperClasses ().empty () &&
2362
- llvm::StringSwitch<bool >(
2363
- Arg->getSuperClasses ().back ().first ->getName ())
2364
- .Case (" StringArgument" , true )
2365
- .Default (false );
2362
+ if (Arg->getSuperClasses ().empty ())
2363
+ return false ;
2364
+ StringRef ArgKind = Arg->getSuperClasses ().back ().first ->getName ();
2365
+ if (ArgKind == " EnumArgument" )
2366
+ return Arg->getValueAsBit (" IsString" );
2367
+ return ArgKind == " StringArgument" ;
2366
2368
}
2367
2369
2368
2370
static bool isVariadicStringLiteralArgument (const Record *Arg) {
2369
- return !Arg->getSuperClasses ().empty () &&
2370
- llvm::StringSwitch<bool >(
2371
- Arg->getSuperClasses ().back ().first ->getName ())
2372
- .Case (" VariadicStringArgument" , true )
2373
- .Default (false );
2371
+ if (Arg->getSuperClasses ().empty ())
2372
+ return false ;
2373
+ StringRef ArgKind = Arg->getSuperClasses ().back ().first ->getName ();
2374
+ if (ArgKind == " VariadicEnumArgument" )
2375
+ return Arg->getValueAsBit (" IsString" );
2376
+ return ArgKind == " VariadicStringArgument" ;
2374
2377
}
2375
2378
2376
2379
static void emitClangAttrVariadicIdentifierArgList (RecordKeeper &Records,
@@ -2393,14 +2396,18 @@ static void emitClangAttrVariadicIdentifierArgList(RecordKeeper &Records,
2393
2396
OS << " #endif // CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST\n\n " ;
2394
2397
}
2395
2398
2399
+ static bool GenerateTargetSpecificAttrChecks (const Record *R,
2400
+ std::vector<StringRef> &Arches,
2401
+ std::string &Test,
2402
+ std::string *FnName);
2403
+
2396
2404
// Emits the list of arguments that should be parsed as unevaluated string
2397
2405
// literals for each attribute.
2398
2406
static void emitClangAttrUnevaluatedStringLiteralList (RecordKeeper &Records,
2399
2407
raw_ostream &OS) {
2400
2408
OS << " #if defined(CLANG_ATTR_STRING_LITERAL_ARG_LIST)\n " ;
2401
- std::vector<Record *> Attrs = Records.getAllDerivedDefinitions (" Attr" );
2402
- for (const auto *Attr : Attrs) {
2403
- std::vector<Record *> Args = Attr->getValueAsListOfDefs (" Args" );
2409
+
2410
+ auto MakeMask = [](ArrayRef<Record *> Args) {
2404
2411
uint32_t Bits = 0 ;
2405
2412
assert (Args.size () <= 32 && " unsupported number of arguments in attribute" );
2406
2413
for (uint32_t N = 0 ; N < Args.size (); ++N) {
@@ -2411,11 +2418,46 @@ static void emitClangAttrUnevaluatedStringLiteralList(RecordKeeper &Records,
2411
2418
break ;
2412
2419
}
2413
2420
}
2414
- if (!Bits)
2421
+ return Bits;
2422
+ };
2423
+
2424
+ auto AddMaskWithTargetCheck = [](const Record *Attr, uint32_t Mask,
2425
+ std::string &MaskStr) {
2426
+ const Record *T = Attr->getValueAsDef (" Target" );
2427
+ std::vector<StringRef> Arches = T->getValueAsListOfStrings (" Arches" );
2428
+ std::string Test;
2429
+ GenerateTargetSpecificAttrChecks (T, Arches, Test, nullptr );
2430
+ MaskStr.append (Test + " ? " + std::to_string (Mask) + " : " );
2431
+ };
2432
+
2433
+ ParsedAttrMap Dupes;
2434
+ ParsedAttrMap Attrs = getParsedAttrList (Records, &Dupes, /* SemaOnly=*/ false );
2435
+ for (const auto &[AttrName, Attr] : Attrs) {
2436
+ std::string MaskStr;
2437
+ if (Attr->isSubClassOf (" TargetSpecificAttr" ) &&
2438
+ !Attr->isValueUnset (" ParseKind" )) {
2439
+ if (uint32_t Mask = MakeMask (Attr->getValueAsListOfDefs (" Args" )))
2440
+ AddMaskWithTargetCheck (Attr, Mask, MaskStr);
2441
+ StringRef ParseKind = Attr->getValueAsString (" ParseKind" );
2442
+ for (const auto &[DupeParseKind, DupAttr] : Dupes) {
2443
+ if (DupeParseKind != ParseKind)
2444
+ continue ;
2445
+ if (uint32_t Mask = MakeMask (DupAttr->getValueAsListOfDefs (" Args" )))
2446
+ AddMaskWithTargetCheck (DupAttr, Mask, MaskStr);
2447
+ }
2448
+ if (!MaskStr.empty ())
2449
+ MaskStr.append (" 0" );
2450
+ } else {
2451
+ if (uint32_t Mask = MakeMask (Attr->getValueAsListOfDefs (" Args" )))
2452
+ MaskStr = std::to_string (Mask);
2453
+ }
2454
+
2455
+ if (MaskStr.empty ())
2415
2456
continue ;
2457
+
2416
2458
// All these spellings have at least one string literal has argument.
2417
2459
forEachUniqueSpelling (*Attr, [&](const FlattenedSpelling &S) {
2418
- OS << " .Case(\" " << S.name () << " \" , " << Bits << " )\n " ;
2460
+ OS << " .Case(\" " << S.name () << " \" , " << MaskStr << " )\n " ;
2419
2461
});
2420
2462
}
2421
2463
OS << " #endif // CLANG_ATTR_STRING_LITERAL_ARG_LIST\n\n " ;
@@ -3404,6 +3446,8 @@ void EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS) {
3404
3446
OS << " }\n " ;
3405
3447
}
3406
3448
3449
+ } // namespace clang
3450
+
3407
3451
// Helper function for GenerateTargetSpecificAttrChecks that alters the 'Test'
3408
3452
// parameter with only a single check type, if applicable.
3409
3453
static bool GenerateTargetSpecificAttrCheck (const Record *R, std::string &Test,
@@ -3570,6 +3614,8 @@ static void GenerateHasAttrSpellingStringSwitch(
3570
3614
OS << " .Default(0);\n " ;
3571
3615
}
3572
3616
3617
+ namespace clang {
3618
+
3573
3619
// Emits list of regular keyword attributes with info about their arguments.
3574
3620
void EmitClangRegularKeywordAttributeInfo (RecordKeeper &Records,
3575
3621
raw_ostream &OS) {
0 commit comments