Skip to content

Commit d1c911f

Browse files
authored
[clang][FMV] Do not omit explicit default target_version attribute. (llvm#96628)
Fixes a crash and cleans up some dead code. namespace Foo { int bar(); __attribute((target_version("default"))) int bar() { return 0; } __attribute((target_version("mops"))) int bar() { return 1; } } $ clang++ --target=aarch64-linux-gnu --rtlib=compiler-rt fmv.cpp None multiversion type isn't valid here UNREACHABLE executed at clang/lib/CodeGen/CodeGenModule.cpp:1840! ... getMangledNameImpl clang::CodeGen::CodeGenModule::getMangledName clang::CodeGen::CodeGenModule::EmitGlobal
1 parent 093ddac commit d1c911f

File tree

6 files changed

+126
-122
lines changed

6 files changed

+126
-122
lines changed

clang/include/clang/Sema/Sema.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4533,8 +4533,7 @@ class Sema final : public SemaBase {
45334533
bool checkTargetAttr(SourceLocation LiteralLoc, StringRef Str);
45344534

45354535
/// Check Target Version attrs
4536-
bool checkTargetVersionAttr(SourceLocation LiteralLoc, Decl *D,
4537-
StringRef &Str, bool &isDefault);
4536+
bool checkTargetVersionAttr(SourceLocation Loc, Decl *D, StringRef Str);
45384537
bool checkTargetClonesAttrString(
45394538
SourceLocation LiteralLoc, StringRef Str, const StringLiteral *Literal,
45404539
Decl *D, bool &HasDefault, bool &HasCommas, bool &HasNotDefault,

clang/lib/Sema/SemaDecl.cpp

Lines changed: 23 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -11201,6 +11201,10 @@ static bool CheckMultiVersionFirstFunction(Sema &S, FunctionDecl *FD) {
1120111201
// otherwise it is treated as a normal function.
1120211202
if (TA && !TA->isDefaultVersion())
1120311203
return false;
11204+
// The target_version attribute only causes Multiversioning if this
11205+
// declaration is NOT the default version.
11206+
if (TVA && TVA->isDefaultVersion())
11207+
return false;
1120411208

1120511209
if ((TA || TVA) && CheckMultiVersionValue(S, FD)) {
1120611210
FD->setInvalidDecl();
@@ -11234,18 +11238,16 @@ static void patchDefaultTargetVersion(FunctionDecl *From, FunctionDecl *To) {
1123411238

1123511239
if (MVKindTo == MultiVersionKind::None &&
1123611240
(MVKindFrom == MultiVersionKind::TargetVersion ||
11237-
MVKindFrom == MultiVersionKind::TargetClones)) {
11238-
To->setIsMultiVersion();
11241+
MVKindFrom == MultiVersionKind::TargetClones))
1123911242
To->addAttr(TargetVersionAttr::CreateImplicit(
1124011243
To->getASTContext(), "default", To->getSourceRange()));
11241-
}
1124211244
}
1124311245

11244-
static bool CheckTargetCausesMultiVersioning(Sema &S, FunctionDecl *OldFD,
11245-
FunctionDecl *NewFD,
11246-
bool &Redeclaration,
11247-
NamedDecl *&OldDecl,
11248-
LookupResult &Previous) {
11246+
static bool CheckDeclarationCausesMultiVersioning(Sema &S, FunctionDecl *OldFD,
11247+
FunctionDecl *NewFD,
11248+
bool &Redeclaration,
11249+
NamedDecl *&OldDecl,
11250+
LookupResult &Previous) {
1124911251
assert(!OldFD->isMultiVersion() && "Unexpected MultiVersion");
1125011252

1125111253
// The definitions should be allowed in any order. If we have discovered
@@ -11256,13 +11258,16 @@ static bool CheckTargetCausesMultiVersioning(Sema &S, FunctionDecl *OldFD,
1125611258
const auto *NewTA = NewFD->getAttr<TargetAttr>();
1125711259
const auto *NewTVA = NewFD->getAttr<TargetVersionAttr>();
1125811260
const auto *OldTA = OldFD->getAttr<TargetAttr>();
11259-
const auto *OldTVA = OldFD->getAttr<TargetVersionAttr>();
11261+
1126011262
// If the old decl is NOT MultiVersioned yet, and we don't cause that
1126111263
// to change, this is a simple redeclaration.
11262-
if ((NewTA && !NewTA->isDefaultVersion() &&
11263-
(!OldTA || OldTA->getFeaturesStr() == NewTA->getFeaturesStr())) ||
11264-
(NewTVA && !NewTVA->isDefaultVersion() &&
11265-
(!OldTVA || OldTVA->getName() == NewTVA->getName())))
11264+
if (NewTA && !NewTA->isDefaultVersion() &&
11265+
(!OldTA || OldTA->getFeaturesStr() == NewTA->getFeaturesStr()))
11266+
return false;
11267+
11268+
// The target_version attribute only causes Multiversioning if this
11269+
// declaration is NOT the default version.
11270+
if (NewTVA && NewTVA->isDefaultVersion())
1126611271
return false;
1126711272

1126811273
// Otherwise, this decl causes MultiVersioning.
@@ -11279,8 +11284,7 @@ static bool CheckTargetCausesMultiVersioning(Sema &S, FunctionDecl *OldFD,
1127911284
}
1128011285

1128111286
// If this is 'default', permit the forward declaration.
11282-
if ((NewTA && NewTA->isDefaultVersion() && !OldTA) ||
11283-
(NewTVA && NewTVA->isDefaultVersion() && !OldTVA)) {
11287+
if (NewTA && NewTA->isDefaultVersion() && !OldTA) {
1128411288
Redeclaration = true;
1128511289
OldDecl = OldFD;
1128611290
OldFD->setIsMultiVersion();
@@ -11312,22 +11316,6 @@ static bool CheckTargetCausesMultiVersioning(Sema &S, FunctionDecl *OldFD,
1131211316
}
1131311317
}
1131411318

11315-
if (NewTVA) {
11316-
llvm::SmallVector<StringRef, 8> Feats;
11317-
OldTVA->getFeatures(Feats);
11318-
llvm::sort(Feats);
11319-
llvm::SmallVector<StringRef, 8> NewFeats;
11320-
NewTVA->getFeatures(NewFeats);
11321-
llvm::sort(NewFeats);
11322-
11323-
if (Feats == NewFeats) {
11324-
S.Diag(NewFD->getLocation(), diag::err_multiversion_duplicate);
11325-
S.Diag(OldFD->getLocation(), diag::note_previous_declaration);
11326-
NewFD->setInvalidDecl();
11327-
return true;
11328-
}
11329-
}
11330-
1133111319
for (const auto *FD : OldFD->redecls()) {
1133211320
const auto *CurTA = FD->getAttr<TargetAttr>();
1133311321
const auto *CurTVA = FD->getAttr<TargetVersionAttr>();
@@ -11683,24 +11671,8 @@ static bool CheckMultiVersionFunction(Sema &S, FunctionDecl *NewFD,
1168311671

1168411672
FunctionDecl *OldFD = OldDecl->getAsFunction();
1168511673

11686-
if (!OldFD->isMultiVersion() && MVKind == MultiVersionKind::None) {
11687-
if (NewTVA || !OldFD->getAttr<TargetVersionAttr>())
11688-
return false;
11689-
if (!NewFD->getType()->getAs<FunctionProtoType>()) {
11690-
// Multiversion declaration doesn't have prototype.
11691-
S.Diag(NewFD->getLocation(), diag::err_multiversion_noproto);
11692-
NewFD->setInvalidDecl();
11693-
} else {
11694-
// No "target_version" attribute is equivalent to "default" attribute.
11695-
NewFD->addAttr(TargetVersionAttr::CreateImplicit(
11696-
S.Context, "default", NewFD->getSourceRange()));
11697-
NewFD->setIsMultiVersion();
11698-
OldFD->setIsMultiVersion();
11699-
OldDecl = OldFD;
11700-
Redeclaration = true;
11701-
}
11702-
return true;
11703-
}
11674+
if (!OldFD->isMultiVersion() && MVKind == MultiVersionKind::None)
11675+
return false;
1170411676

1170511677
// Multiversioned redeclarations aren't allowed to omit the attribute, except
1170611678
// for target_clones and target_version.
@@ -11717,8 +11689,8 @@ static bool CheckMultiVersionFunction(Sema &S, FunctionDecl *NewFD,
1171711689
switch (MVKind) {
1171811690
case MultiVersionKind::Target:
1171911691
case MultiVersionKind::TargetVersion:
11720-
return CheckTargetCausesMultiVersioning(S, OldFD, NewFD, Redeclaration,
11721-
OldDecl, Previous);
11692+
return CheckDeclarationCausesMultiVersioning(
11693+
S, OldFD, NewFD, Redeclaration, OldDecl, Previous);
1172211694
case MultiVersionKind::TargetClones:
1172311695
if (OldFD->isUsed(false)) {
1172411696
NewFD->setInvalidDecl();

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3010,12 +3010,10 @@ bool Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) {
30103010
}
30113011

30123012
bool Sema::checkTargetVersionAttr(SourceLocation LiteralLoc, Decl *D,
3013-
StringRef &AttrStr, bool &isDefault) {
3013+
StringRef AttrStr) {
30143014
enum FirstParam { Unsupported };
30153015
enum SecondParam { None };
30163016
enum ThirdParam { Target, TargetClones, TargetVersion };
3017-
if (AttrStr.trim() == "default")
3018-
isDefault = true;
30193017
llvm::SmallVector<StringRef, 8> Features;
30203018
AttrStr.split(Features, "+");
30213019
for (auto &CurFeature : Features) {
@@ -3035,16 +3033,12 @@ bool Sema::checkTargetVersionAttr(SourceLocation LiteralLoc, Decl *D,
30353033
static void handleTargetVersionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
30363034
StringRef Str;
30373035
SourceLocation LiteralLoc;
3038-
bool isDefault = false;
30393036
if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &LiteralLoc) ||
3040-
S.checkTargetVersionAttr(LiteralLoc, D, Str, isDefault))
3037+
S.checkTargetVersionAttr(LiteralLoc, D, Str))
30413038
return;
3042-
// Do not create default only target_version attribute
3043-
if (!isDefault) {
3044-
TargetVersionAttr *NewAttr =
3045-
::new (S.Context) TargetVersionAttr(S.Context, AL, Str);
3046-
D->addAttr(NewAttr);
3047-
}
3039+
TargetVersionAttr *NewAttr =
3040+
::new (S.Context) TargetVersionAttr(S.Context, AL, Str);
3041+
D->addAttr(NewAttr);
30483042
}
30493043

30503044
static void handleTargetAttr(Sema &S, Decl *D, const ParsedAttr &AL) {

clang/test/CodeGen/attr-target-version.c

Lines changed: 44 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -428,13 +428,6 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de
428428
//
429429
//
430430
// CHECK: Function Attrs: noinline nounwind optnone
431-
// CHECK-LABEL: define {{[^@]+}}@fmv_default
432-
// CHECK-SAME: () #[[ATTR11]] {
433-
// CHECK-NEXT: entry:
434-
// CHECK-NEXT: ret i32 111
435-
//
436-
//
437-
// CHECK: Function Attrs: noinline nounwind optnone
438431
// CHECK-LABEL: define {{[^@]+}}@fmv_c._Mssbs
439432
// CHECK-SAME: () #[[ATTR11]] {
440433
// CHECK-NEXT: entry:
@@ -637,22 +630,18 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de
637630
//
638631
//
639632
// CHECK: Function Attrs: noinline nounwind optnone
640-
// CHECK-LABEL: define {{[^@]+}}@recur
633+
// CHECK-LABEL: define {{[^@]+}}@fmv_default
641634
// CHECK-SAME: () #[[ATTR11]] {
642635
// CHECK-NEXT: entry:
643-
// CHECK-NEXT: call void @reca()
644-
// CHECK-NEXT: ret void
636+
// CHECK-NEXT: ret i32 111
645637
//
646638
//
647639
// CHECK: Function Attrs: noinline nounwind optnone
648-
// CHECK-LABEL: define {{[^@]+}}@main
640+
// CHECK-LABEL: define {{[^@]+}}@recur
649641
// CHECK-SAME: () #[[ATTR11]] {
650642
// CHECK-NEXT: entry:
651-
// CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4
652-
// CHECK-NEXT: store i32 0, ptr [[RETVAL]], align 4
653-
// CHECK-NEXT: call void @recur()
654-
// CHECK-NEXT: [[CALL:%.*]] = call i32 @goo()
655-
// CHECK-NEXT: ret i32 [[CALL]]
643+
// CHECK-NEXT: call void @reca()
644+
// CHECK-NEXT: ret void
656645
//
657646
//
658647
// CHECK: Function Attrs: noinline nounwind optnone
@@ -818,6 +807,17 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de
818807
//
819808
//
820809
// CHECK: Function Attrs: noinline nounwind optnone
810+
// CHECK-LABEL: define {{[^@]+}}@main
811+
// CHECK-SAME: () #[[ATTR11]] {
812+
// CHECK-NEXT: entry:
813+
// CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4
814+
// CHECK-NEXT: store i32 0, ptr [[RETVAL]], align 4
815+
// CHECK-NEXT: call void @recur()
816+
// CHECK-NEXT: [[CALL:%.*]] = call i32 @goo()
817+
// CHECK-NEXT: ret i32 [[CALL]]
818+
//
819+
//
820+
// CHECK: Function Attrs: noinline nounwind optnone
821821
// CHECK-LABEL: define {{[^@]+}}@fmv_inline._Mf64mmMpmullMsha1
822822
// CHECK-SAME: () #[[ATTR22:[0-9]+]] {
823823
// CHECK-NEXT: entry:
@@ -1020,20 +1020,6 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de
10201020
//
10211021
//
10221022
// CHECK-NOFMV: Function Attrs: noinline nounwind optnone
1023-
// CHECK-NOFMV-LABEL: define {{[^@]+}}@fmv_default
1024-
// CHECK-NOFMV-SAME: () #[[ATTR0]] {
1025-
// CHECK-NOFMV-NEXT: entry:
1026-
// CHECK-NOFMV-NEXT: ret i32 111
1027-
//
1028-
//
1029-
// CHECK-NOFMV: Function Attrs: noinline nounwind optnone
1030-
// CHECK-NOFMV-LABEL: define {{[^@]+}}@fmv_c
1031-
// CHECK-NOFMV-SAME: () #[[ATTR0]] {
1032-
// CHECK-NOFMV-NEXT: entry:
1033-
// CHECK-NOFMV-NEXT: ret void
1034-
//
1035-
//
1036-
// CHECK-NOFMV: Function Attrs: noinline nounwind optnone
10371023
// CHECK-NOFMV-LABEL: define {{[^@]+}}@goo
10381024
// CHECK-NOFMV-SAME: () #[[ATTR0]] {
10391025
// CHECK-NOFMV-NEXT: entry:
@@ -1053,22 +1039,25 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de
10531039
//
10541040
//
10551041
// CHECK-NOFMV: Function Attrs: noinline nounwind optnone
1056-
// CHECK-NOFMV-LABEL: define {{[^@]+}}@recur
1042+
// CHECK-NOFMV-LABEL: define {{[^@]+}}@fmv_c
10571043
// CHECK-NOFMV-SAME: () #[[ATTR0]] {
10581044
// CHECK-NOFMV-NEXT: entry:
1059-
// CHECK-NOFMV-NEXT: call void @reca()
10601045
// CHECK-NOFMV-NEXT: ret void
10611046
//
10621047
//
10631048
// CHECK-NOFMV: Function Attrs: noinline nounwind optnone
1064-
// CHECK-NOFMV-LABEL: define {{[^@]+}}@main
1049+
// CHECK-NOFMV-LABEL: define {{[^@]+}}@fmv_default
10651050
// CHECK-NOFMV-SAME: () #[[ATTR0]] {
10661051
// CHECK-NOFMV-NEXT: entry:
1067-
// CHECK-NOFMV-NEXT: [[RETVAL:%.*]] = alloca i32, align 4
1068-
// CHECK-NOFMV-NEXT: store i32 0, ptr [[RETVAL]], align 4
1069-
// CHECK-NOFMV-NEXT: call void @recur()
1070-
// CHECK-NOFMV-NEXT: [[CALL:%.*]] = call i32 @goo()
1071-
// CHECK-NOFMV-NEXT: ret i32 [[CALL]]
1052+
// CHECK-NOFMV-NEXT: ret i32 111
1053+
//
1054+
//
1055+
// CHECK-NOFMV: Function Attrs: noinline nounwind optnone
1056+
// CHECK-NOFMV-LABEL: define {{[^@]+}}@recur
1057+
// CHECK-NOFMV-SAME: () #[[ATTR0]] {
1058+
// CHECK-NOFMV-NEXT: entry:
1059+
// CHECK-NOFMV-NEXT: call void @reca()
1060+
// CHECK-NOFMV-NEXT: ret void
10721061
//
10731062
//
10741063
// CHECK-NOFMV: Function Attrs: noinline nounwind optnone
@@ -1089,31 +1078,42 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de
10891078
//
10901079
//
10911080
// CHECK-NOFMV: Function Attrs: noinline nounwind optnone
1092-
// CHECK-NOFMV-LABEL: define {{[^@]+}}@unused_with_default_def
1081+
// CHECK-NOFMV-LABEL: define {{[^@]+}}@unused_with_implicit_default_def
10931082
// CHECK-NOFMV-SAME: () #[[ATTR0]] {
10941083
// CHECK-NOFMV-NEXT: entry:
10951084
// CHECK-NOFMV-NEXT: ret i32 1
10961085
//
10971086
//
10981087
// CHECK-NOFMV: Function Attrs: noinline nounwind optnone
1099-
// CHECK-NOFMV-LABEL: define {{[^@]+}}@unused_with_implicit_default_def
1088+
// CHECK-NOFMV-LABEL: define {{[^@]+}}@unused_with_implicit_forward_default_def
11001089
// CHECK-NOFMV-SAME: () #[[ATTR0]] {
11011090
// CHECK-NOFMV-NEXT: entry:
1102-
// CHECK-NOFMV-NEXT: ret i32 1
1091+
// CHECK-NOFMV-NEXT: ret i32 0
11031092
//
11041093
//
11051094
// CHECK-NOFMV: Function Attrs: noinline nounwind optnone
1106-
// CHECK-NOFMV-LABEL: define {{[^@]+}}@unused_with_implicit_forward_default_def
1095+
// CHECK-NOFMV-LABEL: define {{[^@]+}}@default_def_with_version_decls
11071096
// CHECK-NOFMV-SAME: () #[[ATTR0]] {
11081097
// CHECK-NOFMV-NEXT: entry:
11091098
// CHECK-NOFMV-NEXT: ret i32 0
11101099
//
11111100
//
11121101
// CHECK-NOFMV: Function Attrs: noinline nounwind optnone
1113-
// CHECK-NOFMV-LABEL: define {{[^@]+}}@default_def_with_version_decls
1102+
// CHECK-NOFMV-LABEL: define {{[^@]+}}@main
11141103
// CHECK-NOFMV-SAME: () #[[ATTR0]] {
11151104
// CHECK-NOFMV-NEXT: entry:
1116-
// CHECK-NOFMV-NEXT: ret i32 0
1105+
// CHECK-NOFMV-NEXT: [[RETVAL:%.*]] = alloca i32, align 4
1106+
// CHECK-NOFMV-NEXT: store i32 0, ptr [[RETVAL]], align 4
1107+
// CHECK-NOFMV-NEXT: call void @recur()
1108+
// CHECK-NOFMV-NEXT: [[CALL:%.*]] = call i32 @goo()
1109+
// CHECK-NOFMV-NEXT: ret i32 [[CALL]]
1110+
//
1111+
//
1112+
// CHECK-NOFMV: Function Attrs: noinline nounwind optnone
1113+
// CHECK-NOFMV-LABEL: define {{[^@]+}}@unused_with_default_def
1114+
// CHECK-NOFMV-SAME: () #[[ATTR0]] {
1115+
// CHECK-NOFMV-NEXT: entry:
1116+
// CHECK-NOFMV-NEXT: ret i32 1
11171117
//
11181118
//.
11191119
// CHECK: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+flagm,+fp-armv8,+fp16fml,+fullfp16,+neon,+rand,-v9.5a" }

0 commit comments

Comments
 (0)