Skip to content

Commit e8f3492

Browse files
Always register asm attribute first in a Decl.
Previously, clang's SemaDecl processed `asm` attributes after every other attribute in the Decl, unlike gcc and clang's own parser which requires `asm` attributes to be the first one in the declaration (see llvm#162556). Therefore, move the processing of `asm` attributes to be the first one in the attributes list. Signed-off-by: Giuliano Belinassi <[email protected]>
1 parent caacfff commit e8f3492

File tree

4 files changed

+100
-59
lines changed

4 files changed

+100
-59
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,17 @@ AST Dumping Potentially Breaking Changes
128128

129129
- Default arguments of template template parameters are pretty-printed now.
130130

131+
- Pretty-printing of ``asm`` attributes are now always the first attribute
132+
on the right side of the declaration. Before we had, e.g.:
133+
134+
``__attribute__(("visibility")) asm("string")``
135+
136+
Now we have:
137+
138+
``asm("string") __attribute__(("visibility"))``
139+
140+
Which is accepted by both clang and gcc parsers.
141+
131142
Clang Frontend Potentially Breaking Changes
132143
-------------------------------------------
133144
- Members of anonymous unions/structs are now injected as ``IndirectFieldDecl``

clang/include/clang/Sema/Sema.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3961,6 +3961,14 @@ class Sema final : public SemaBase {
39613961
bool &AddToScope,
39623962
ArrayRef<BindingDecl *> Bindings = {});
39633963

3964+
private:
3965+
3966+
// Perform a check on an AsmLabel to verify its consistency and emit
3967+
// diagnostics in case of an error.
3968+
void CheckAsmLabel(Scope *S, Expr *AsmLabelExpr, StorageClass SC,
3969+
TypeSourceInfo *TInfo, VarDecl *);
3970+
public:
3971+
39643972
/// Perform semantic checking on a newly-created variable
39653973
/// declaration.
39663974
///

clang/lib/Sema/SemaDecl.cpp

Lines changed: 78 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -7640,6 +7640,59 @@ static bool isMainVar(DeclarationName Name, VarDecl *VD) {
76407640
VD->isExternC());
76417641
}
76427642

7643+
void Sema::CheckAsmLabel(Scope *S, Expr *E, StorageClass SC,
7644+
TypeSourceInfo *TInfo, VarDecl *NewVD) {
7645+
7646+
// Quickly return if the function does not have an `asm` attribute.
7647+
if (E == nullptr)
7648+
return;
7649+
7650+
// The parser guarantees this is a string.
7651+
StringLiteral *SE = cast<StringLiteral>(E);
7652+
StringRef Label = SE->getString();
7653+
QualType R = TInfo->getType();
7654+
if (S->getFnParent() != nullptr) {
7655+
switch (SC) {
7656+
case SC_None:
7657+
case SC_Auto:
7658+
Diag(E->getExprLoc(), diag::warn_asm_label_on_auto_decl) << Label;
7659+
break;
7660+
case SC_Register:
7661+
// Local Named register
7662+
if (!Context.getTargetInfo().isValidGCCRegisterName(Label) &&
7663+
DeclAttrsMatchCUDAMode(getLangOpts(), getCurFunctionDecl()))
7664+
Diag(E->getExprLoc(), diag::err_asm_unknown_register_name) << Label;
7665+
break;
7666+
case SC_Static:
7667+
case SC_Extern:
7668+
case SC_PrivateExtern:
7669+
break;
7670+
}
7671+
} else if (SC == SC_Register) {
7672+
// Global Named register
7673+
if (DeclAttrsMatchCUDAMode(getLangOpts(), NewVD)) {
7674+
const auto &TI = Context.getTargetInfo();
7675+
bool HasSizeMismatch;
7676+
7677+
if (!TI.isValidGCCRegisterName(Label))
7678+
Diag(E->getExprLoc(), diag::err_asm_unknown_register_name) << Label;
7679+
else if (!TI.validateGlobalRegisterVariable(Label,
7680+
Context.getTypeSize(R),
7681+
HasSizeMismatch))
7682+
Diag(E->getExprLoc(), diag::err_asm_invalid_global_var_reg) << Label;
7683+
else if (HasSizeMismatch)
7684+
Diag(E->getExprLoc(), diag::err_asm_register_size_mismatch) << Label;
7685+
}
7686+
7687+
if (!R->isIntegralType(Context) && !R->isPointerType()) {
7688+
Diag(TInfo->getTypeLoc().getBeginLoc(),
7689+
diag::err_asm_unsupported_register_type)
7690+
<< TInfo->getTypeLoc().getSourceRange();
7691+
NewVD->setInvalidDecl(true);
7692+
}
7693+
}
7694+
}
7695+
76437696
NamedDecl *Sema::ActOnVariableDeclarator(
76447697
Scope *S, Declarator &D, DeclContext *DC, TypeSourceInfo *TInfo,
76457698
LookupResult &Previous, MultiTemplateParamsArg TemplateParamLists,
@@ -8124,6 +8177,26 @@ NamedDecl *Sema::ActOnVariableDeclarator(
81248177
}
81258178
}
81268179

8180+
if (Expr *E = D.getAsmLabel()) {
8181+
// The parser guarantees this is a string.
8182+
StringLiteral *SE = cast<StringLiteral>(E);
8183+
StringRef Label = SE->getString();
8184+
8185+
// Insert the asm attribute.
8186+
NewVD->addAttr(AsmLabelAttr::Create(Context, Label, SE->getStrTokenLoc(0)));
8187+
} else if (!ExtnameUndeclaredIdentifiers.empty()) {
8188+
llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*>::iterator I =
8189+
ExtnameUndeclaredIdentifiers.find(NewVD->getIdentifier());
8190+
if (I != ExtnameUndeclaredIdentifiers.end()) {
8191+
if (isDeclExternC(NewVD)) {
8192+
NewVD->addAttr(I->second);
8193+
ExtnameUndeclaredIdentifiers.erase(I);
8194+
} else
8195+
Diag(NewVD->getLocation(), diag::warn_redefine_extname_not_applied)
8196+
<< /*Variable*/1 << NewVD;
8197+
}
8198+
}
8199+
81278200
// Handle attributes prior to checking for duplicates in MergeVarDecl
81288201
ProcessDeclAttributes(S, NewVD, D);
81298202

@@ -8174,65 +8247,11 @@ NamedDecl *Sema::ActOnVariableDeclarator(
81748247
if (getLangOpts().ObjCAutoRefCount && ObjC().inferObjCARCLifetime(NewVD))
81758248
NewVD->setInvalidDecl();
81768249

8177-
// Handle GNU asm-label extension (encoded as an attribute).
8178-
if (Expr *E = D.getAsmLabel()) {
8179-
// The parser guarantees this is a string.
8180-
StringLiteral *SE = cast<StringLiteral>(E);
8181-
StringRef Label = SE->getString();
8182-
if (S->getFnParent() != nullptr) {
8183-
switch (SC) {
8184-
case SC_None:
8185-
case SC_Auto:
8186-
Diag(E->getExprLoc(), diag::warn_asm_label_on_auto_decl) << Label;
8187-
break;
8188-
case SC_Register:
8189-
// Local Named register
8190-
if (!Context.getTargetInfo().isValidGCCRegisterName(Label) &&
8191-
DeclAttrsMatchCUDAMode(getLangOpts(), getCurFunctionDecl()))
8192-
Diag(E->getExprLoc(), diag::err_asm_unknown_register_name) << Label;
8193-
break;
8194-
case SC_Static:
8195-
case SC_Extern:
8196-
case SC_PrivateExtern:
8197-
break;
8198-
}
8199-
} else if (SC == SC_Register) {
8200-
// Global Named register
8201-
if (DeclAttrsMatchCUDAMode(getLangOpts(), NewVD)) {
8202-
const auto &TI = Context.getTargetInfo();
8203-
bool HasSizeMismatch;
8204-
8205-
if (!TI.isValidGCCRegisterName(Label))
8206-
Diag(E->getExprLoc(), diag::err_asm_unknown_register_name) << Label;
8207-
else if (!TI.validateGlobalRegisterVariable(Label,
8208-
Context.getTypeSize(R),
8209-
HasSizeMismatch))
8210-
Diag(E->getExprLoc(), diag::err_asm_invalid_global_var_reg) << Label;
8211-
else if (HasSizeMismatch)
8212-
Diag(E->getExprLoc(), diag::err_asm_register_size_mismatch) << Label;
8213-
}
8214-
8215-
if (!R->isIntegralType(Context) && !R->isPointerType()) {
8216-
Diag(TInfo->getTypeLoc().getBeginLoc(),
8217-
diag::err_asm_unsupported_register_type)
8218-
<< TInfo->getTypeLoc().getSourceRange();
8219-
NewVD->setInvalidDecl(true);
8220-
}
8221-
}
8222-
8223-
NewVD->addAttr(AsmLabelAttr::Create(Context, Label, SE->getStrTokenLoc(0)));
8224-
} else if (!ExtnameUndeclaredIdentifiers.empty()) {
8225-
llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*>::iterator I =
8226-
ExtnameUndeclaredIdentifiers.find(NewVD->getIdentifier());
8227-
if (I != ExtnameUndeclaredIdentifiers.end()) {
8228-
if (isDeclExternC(NewVD)) {
8229-
NewVD->addAttr(I->second);
8230-
ExtnameUndeclaredIdentifiers.erase(I);
8231-
} else
8232-
Diag(NewVD->getLocation(), diag::warn_redefine_extname_not_applied)
8233-
<< /*Variable*/1 << NewVD;
8234-
}
8235-
}
8250+
// Check the ASM label here, as we need to know all other attributes of the
8251+
// Decl first. Otherwise, we can't know if the asm label refers to the
8252+
// host or device in a CUDA context. The device has other registers than
8253+
// host and we must know where the function will be placed.
8254+
CheckAsmLabel(S, D.getAsmLabel(), SC, TInfo, NewVD);
82368255

82378256
// Find the shadowed declaration before filtering for scope.
82388257
NamedDecl *ShadowedDecl = D.getCXXScopeSpec().isEmpty()

clang/test/Sema/attr-print.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,6 @@ int * __sptr * __ptr32 ppsp32;
3535

3636
// CHECK: __attribute__((availability(macos, strict, introduced=10.6)));
3737
void f6(int) __attribute__((availability(macosx,strict,introduced=10.6)));
38+
39+
// CHECK: _libc_intl_domainname asm("__gi__libc_intl_domainname") __attribute__((visibility("hidden")));
40+
extern const char _libc_intl_domainname[]; extern typeof (_libc_intl_domainname) _libc_intl_domainname asm("__gi__libc_intl_domainname") __attribute__((visibility("hidden")));

0 commit comments

Comments
 (0)